Ich habe eine App erstellt, die mit GUI mit Python funktioniert. Ich werde diese Zeit kurz zusammenfassen.
Beispielsweise ist es ein Bild, das eine Python-Datei unter einem bestimmten Ordner öffnet, einzeln verarbeitet und anzeigt, dass XX von XX ausgeführt wird.
Erstellen Sie zunächst eine Klasse `` `FileList```, die Dateien mit einer bestimmten Erweiterung sammelt und eine Liste erstellt.
filelist.py
import os
class FileList():
''' store file list'''
def __init__(self, root_dir, ext):
self.root_dir = root_dir
self.ext = ext
self.files = []
def retrieve(self):
for rd, _, fl in os.walk(self.root_dir):
for f in fl:
_, fext = os.path.splitext(f)
if fext == self.ext:
self.files.append(os.path.join(rd, f))
def print(self):
for f in self.files:
print(f)
Es ist eine enttäuschend einfache Klasse.
Ich werde es versuchen.
Ja, vielleicht richtig.
Entwerfen Sie die GUI. Die erforderlichen Elemente sind wie folgt.
Die Teile zum Eingeben des Zielordners sollten eine Schaltfläche "Nach Ordner suchen" und ein Textfeld haben, in dem der angegebene Ordner angezeigt wird.
Der Teil zum Anweisen der Ausführung sollte eine Schaltfläche "Ausführen" haben.
Für den Teil, der den Fortschritt anzeigt, wird der Name der zu verarbeitenden Datei im Textfeld angezeigt, und die Gesamtfortschrittsrate wird in der Fortschrittsleiste angezeigt.
Ich denke, dass diese Teileplatzierung leicht mit einem geeigneten GUI-Designtool durchgeführt werden kann, aber vorerst werde ich sie von Hand schreiben.
Beginnen Sie grundsätzlich mit Erste Programme in PyQt5.
guimain.py
import sys
import os
from PyQt5.QtWidgets import (QWidget, QApplication,
QPushButton, QLineEdit,
QHBoxLayout, QVBoxLayout,
QTextEdit, QProgressBar,
QFileDialog)
from PyQt5.QtCore import Qt
class MainWidget(QWidget):
dirname = ''
step = 0
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.initUI()
def initUI(self):
self.resize(480, 360)
self.txtFolder = QLineEdit()
self.btnFolder = QPushButton('Referenz...')
hb1 = QHBoxLayout()
hb1.addWidget(self.txtFolder)
hb1.addWidget(self.btnFolder)
self.btnExec = QPushButton('Lauf')
self.btnExec.setEnabled(False)
hb2 = QHBoxLayout()
hb2.addWidget(self.btnExec)
self.txtLog = QTextEdit()
self.pbar = QProgressBar()
self.pbar.setTextVisible(False)
layout = QVBoxLayout()
layout.addLayout(hb1)
layout.addLayout(hb2)
layout.addWidget(self.txtLog)
layout.addWidget(self.pbar)
self.setLayout(layout)
self.setWindowTitle('PyQt5 Sample')
def main(args):
app = QApplication(args)
dialog = MainWidget()
dialog.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main(sys.argv)
Es ist fast wie erwartet.
In btnFolder als angeklicktes Ereignis definiert.
self.btnFolder.clicked.connect(self.show_folder_dialog)
def show_folder_dialog(self):
''' open dialog and set to foldername '''
dirname = QFileDialog.getExistingDirectory(self,
'open folder',
os.path.expanduser('.'),
QFileDialog.ShowDirsOnly)
if dirname:
self.dirname = dirname.replace('/', os.sep)
self.txtFolder.setText(self.dirname)
self.btnExec.setEnabled(True)
self.step = 0
Öffnen Sie den Ordner-Spezifikationsdialog und aktivieren Sie die Schaltfläche "Ausführen".
Sammeln Sie ".py" -Dateien unter dem angegebenen Ordner und zeigen Sie den Dateinamen in txtLog an. Zusätzlich wird der Fortschritt während der Ausführung durch einen Fortschrittsbalken dargestellt.
guimain.py
from filelist import FileList
Ändern Sie die FileList-Klasse geringfügig gegenüber der Originalversion.
filelist.py
class FileList():
''' store file list'''
def __init__(self):
self.root_dir = ''
self.ext = ''
self.files = []
def setup(self, root_dir, ext):
self.root_dir = root_dir
self.ext = ext
self.retrieve()
def retrieve(self):
self.files = []
for rd, _, fl in os.walk(self.root_dir):
for f in fl:
_, fext = os.path.splitext(f)
if fext == self.ext:
self.files.append(os.path.join(rd, f))
def print(self):
for f in self.files:
print(f)
init()
damit,root_dir
Wannext
Wurde angegeben, aber neu definiertsetup()
Wechseln Sie zur Methode.
Da das GUI-Array im GUI-Programm auf einem Mutti-Thread ausgeführt wird, wird die FileList-Klasse von QThread geerbt, sodass die Dateidateisammlung selbst auch auf Multi-Thread funktioniert.
Es implementiert auch eine Funktion zum Senden eines Signals, sodass der Fortschrittsbalken für jeden Prozess verschoben werden kann.
Ursprünglich wird in process_file () beispielsweise, wenn es sich um eine Bilddatei handelt, eine gewisse Bearbeitung durchgeführt. In diesem Beispiel ist dies jedoch nicht der Hauptpunkt, sodass ich vorerst nichts unternehmen werde.
filelist.py
import os
import sys
from PyQt5.QtCore import pyqtSignal, QMutexLocker, QMutex, QThread
class FileList(QThread):
''' store file list'''
sig_file = pyqtSignal(str)
def __init__(self, parent=None):
super(FileList, self).__init__(parent)
self.stopped = False
self.mutex = QMutex()
def setup(self, root_dir, ext):
self.root_dir = root_dir
self.ext = ext
self.retrieve()
self.stopped = False
def stop(self):
with QMutexLocker(self.mutex):
self.stopped = True
def run(self):
for f in self.files:
fname = f
self.process_file(fname)
self.sig_file.emit(fname) #Signalübertragung
self.stop()
self.finished.emit() #Signalübertragung
def retrieve(self):
''' root_Holen Sie sich eine Datei mit der Erweiterung ext aus dir'''
self.files = []
for rd, _, fl in os.walk(self.root_dir):
for f in fl:
_, fext = os.path.splitext(f)
if fext == self.ext:
self.files.append(os.path.join(rd, f))
self.length = len(self.files)
def process_file(self, path):
'''Tu vorerst nichts'''
cnt = 0
if os.path.exists(path):
cnt += 1
else:
cnt = 0
def print(self):
for f in self.files:
print(f)
def main(args):
root_dir = '.'
ext = '.py'
if len(args) == 3:
root_dir = args[1]
ext = args[2]
fileList = FileList()
fileList.setup(root_dir, ext)
fileList.print()
if __name__ == '__main__':
main(sys.argv)
Wenn Sie auf diese FileList-Klasse verweisen und die Schaltfläche drücken, lautet guimain.py, das den angegebenen Ordner durchsucht und den Vorgang anzeigt, wie folgt.
guimain.py
import sys
import os
from PyQt5.QtWidgets import (QWidget, QApplication, QPushButton, QLineEdit,
QHBoxLayout, QVBoxLayout, QTextEdit, QProgressBar,
QFileDialog)
from PyQt5.QtCore import pyqtSlot, Qt
from filelist import FileList
class MainWidget(QWidget):
dirname = ''
step = 0
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.initUI()
self.fileList = FileList()
self.fileList.sig_file.connect(self.update_status)
self.fileList.finished.connect(self.finish_process)
def initUI(self):
self.resize(480, 360)
self.txtFolder = QLineEdit()
self.txtFolder.setReadOnly(True)
self.btnFolder = QPushButton('Referenz...')
self.btnFolder.clicked.connect(self.show_folder_dialog)
hb1 = QHBoxLayout()
hb1.addWidget(self.txtFolder)
hb1.addWidget(self.btnFolder)
self.btnExec = QPushButton('Lauf')
self.btnExec.clicked.connect(self.exec_process)
self.btnExec.setEnabled(False)
self.btnExec.setVisible(True)
self.btnExit = QPushButton('Ende')
self.btnExit.setVisible(False) #Invalidierung
self.btnExit.setEnabled(False) #Nicht zeigen
self.btnExit.clicked.connect(self.close)
hb2 = QHBoxLayout()
hb2.addWidget(self.btnExec)
hb2.addWidget(self.btnExit) #Unsichtbare Schaltfläche im Ausgangszustand hinzugefügt
self.txtLog = QTextEdit()
self.txtLog.setReadOnly(True)
self.pbar = QProgressBar()
self.pbar.setTextVisible(False)
layout = QVBoxLayout()
layout.addLayout(hb1)
layout.addLayout(hb2)
layout.addWidget(self.txtLog)
layout.addWidget(self.pbar)
self.setLayout(layout)
self.setWindowTitle('PyQt5 Sample')
def show_folder_dialog(self):
''' open dialog and set to foldername '''
dirname = QFileDialog.getExistingDirectory(self,
'open folder',
os.path.expanduser('.'),
QFileDialog.ShowDirsOnly)
if dirname:
self.dirname = dirname.replace('/', os.sep) #Konvertieren Sie den Verzeichnisbegrenzer entsprechend dem Betriebssystem
self.txtFolder.setText(self.dirname)
self.btnExec.setEnabled(True)
self.step = 0
def print_log(self, logstr):
self.txtLog.append(logstr)
@pyqtSlot()
def exec_process(self):
if os.path.exists(self.dirname):
try:
QApplication.setOverrideCursor(Qt.WaitCursor)
self.fileList.setup(self.dirname, '.py')
maxCnt = self.fileList.length
self.pbar.setValue(0)
self.pbar.setMinimum(0)
self.pbar.setMaximum(maxCnt)
self.fileList.start()
except Exception as e:
self.print_log(str(e))
finally:
QApplication.restoreOverrideCursor()
else:
self.print_log('{0} is not exists'.format(self.dirname))
@pyqtSlot(str)
def update_status(self, filename):
self.txtLog.append(filename)
self.step += 1
self.pbar.setValue(self.step) #Fortschrittsanzeige
@pyqtSlot()
def finish_process(self):
self.fileList.wait()
#Verstecken Sie die Schaltfläche "Ausführen"
self.btnExec.setEnabled(False)
self.btnExec.setVisible(False)
#Zeigen Sie die Endschaltfläche
self.btnExit.setEnabled(True)
self.btnExit.setVisible(True)
def main(args):
app = QApplication(args)
dialog = MainWidget()
dialog.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main(sys.argv)
Es wird nervig, wenn Sie es also wie oben schreiben, wird es vorerst funktionieren.
In FileList.run () wird nacheinander self.sig_file.emit (fname)
`ein Signal gesendet und durch Empfang mit guimain.update_status () der Fortschrittsbalken angezeigt. Sie können nacheinander fortfahren.
Ich habe eine GUI-App in Python geschrieben. Der Schlüssel ist, QThread zu erben.
Recommended Posts