Ich habe eine GUI-App mit Python + PyQt5 erstellt

Ich habe eine App erstellt, die mit GUI mit Python funktioniert. Ich werde diese Zeit kurz zusammenfassen.

Spezifikationen: Erstellen Sie eine Liste von Dateien mit einer bestimmten Erweiterung, verarbeiten Sie sie einzeln und zeigen Sie ihren Fortschritt an

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 eine Klasse, die Dateien mit einer bestimmten Erweiterung sammelt

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.

20170625001.png

Ja, vielleicht richtig.

GUI-Design

Entwerfen Sie die GUI. Die erforderlichen Elemente sind wie folgt.

  1. Teile zur Eingabe des Zielordners
  2. Teile zur Anweisung der Ausführung
  3. Teile, die den Fortschritt anzeigen

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.

20170625002.png

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)

20170626001.png

Es ist fast wie erwartet.

Implementierung

Funktion der Schaltfläche "Durchsuchen ..." (btnFolder)

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".

Funktion der Schaltfläche "Ausführen" (btnExec)

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.

Importieren Sie die FileList-Klasse

guimain.py


from filelist import FileList

Führen Sie die Methode retrieve () der FileList-Klasse aus

Ä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_dirWannextWurde angegeben, aber neu definiertsetup()Wechseln Sie zur Methode.

Zur Vererbung von QThread

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)

Viel schnelle Beschleunigung in der zweiten Hälfte

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.


Zusammenfassung

Ich habe eine GUI-App in Python geschrieben. Der Schlüssel ist, QThread zu erben.

Der heutige Code

Recommended Posts

Ich habe eine GUI-App mit Python + PyQt5 erstellt
Ich habe mit Python eine Lotterie gemacht.
Ich habe mit Python einen Daemon erstellt
Ich habe mit Python einen Zeichenzähler erstellt
Ich habe eine einfache Buch-App mit Python + Flask ~ Introduction ~ erstellt
Ich habe mit Python eine Hex-Map erstellt
Ich habe mit Python ein schurkenhaftes Spiel gemacht
Ich habe mit Python einen einfachen Blackjack gemacht
Ich habe mit Python eine Einstellungsdatei erstellt
Ich habe eine WEB-Bewerbung bei Django gemacht
Ich habe mit Python einen Neuronensimulator erstellt
Ich habe mit Python eine Bot-Wettervorhersage gemacht.
Ich habe versucht, mit Python einen Twitter-Blocker für faule Mädchen zu machen
[Python] Ich habe mit Tkinter einen Youtube Downloader erstellt.
Ich habe mit Python ein Bin-Picking-Spiel gemacht
Mattermost Bot mit Python gemacht (+ Flask)
Ich habe einen Blackjack mit Python gemacht!
Ich habe einen Python-Text gemacht
Ich habe mit Python einen Blackjack gemacht.
[GUI mit Python] PyQt5-Vorbereitung-
Ich habe Wordcloud mit Python gemacht.
[GUI mit Python] PyQt5 -Paint-
Ich habe einen Twitter BOT mit GAE (Python) gemacht (mit einer Referenz)
Ich habe mit Python ein Weihnachtsbaum-Beleuchtungsspiel gemacht
Ich habe mit Python eine App für die Benachrichtigung über Netznachrichten erstellt
Ich habe eine Python3-Umgebung unter Ubuntu mit direnv erstellt.
Ich habe versucht, LINE BOT mit Python und Heroku zu machen
[GUI mit Python] PyQt5 -Widget II-
Lassen Sie uns eine GUI mit Python erstellen.
Ich habe mit PyQt5 und Python3 gespielt
[GUI mit Python] PyQt5 -Custom Widget-
Ich habe ein einfaches Tippspiel mit tkinter of Python gemacht
Ich habe ein Paket erstellt, um Zeitreihen mit Python zu filtern
Ich habe mit Tkinter of Python ein Puzzlespiel (wie) gemacht
Ich habe ein Pay-Management-Programm in Python erstellt!
Ich habe eine Heatmap mit Seaborn [Python] gezeichnet.
Ich habe eine funktionale Sprache mit Python ausprobiert
[Python] Eine schnelle Webanwendung mit Bottle!
Was ich mit Python-Arrays gemacht habe
Ich habe ein Lebensspiel mit Numpy gemacht
Führen Sie eine Python-Webanwendung mit Docker aus
Ich habe einen Hanko-Generator mit GAN gemacht
Nachdem ich Python3 studiert hatte, machte ich einen Slackbot
Ich habe eine einfache Schaltung mit Python gemacht (AND, OR, NOR, etc.)
Ich habe ein Paket erstellt, das morphologische Analysegeräte mit Python vergleichen kann
Ich habe mit Python, Flask und Heroku ein Nyanko-Tweet-Formular erstellt
Ich habe viele Dateien für die RDP-Verbindung mit Python erstellt
[Python] Ich habe einen Bildbetrachter mit einer einfachen Sortierfunktion erstellt.
Ich habe ein Shuffle gemacht, das mit Python zurückgesetzt (zurückgesetzt) werden kann
Ich habe versucht, mit Python eine 2-Kanal-Post-Benachrichtigungsanwendung zu erstellen
Ich habe versucht, eine ToDo-App mit einer Flasche mit Python zu erstellen
Ich habe einen Pokerspielserver Chat-Holdem mit Websocket mit Python erstellt
Ich habe einen Stempelersatzbot mit Linie gemacht
Führen Sie Python-Skripte in C # -GUI-Anwendungen aus
Ich habe eine Python-Wörterbuchdatei für Neocomplete erstellt
〇✕ Ich habe ein Spiel gemacht
Ich habe ein Tool zum automatischen Durchsuchen mehrerer Websites mit Selenium (Python) erstellt.
Ich habe eine Webanwendung in Python erstellt, die Markdown in HTML konvertiert