J'ai créé une application qui fonctionne avec une interface graphique avec python. Je vais résumer brièvement cette période.
Par exemple, il s'agit d'une image qui ouvre un fichier Python dans un dossier spécifique, le traite un par un et affiche que XX sur XX est en cours d'exécution.
Tout d'abord, créez une classe `` FileList '' qui collecte les fichiers avec une extension spécifique et crée une liste.
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)
C'est une classe extrêmement facile.
Je vais essayer.
Ouais, peut-être vrai.
Concevez l'interface graphique. Les éléments requis sont les suivants.
Les parties pour entrer dans le dossier cible doivent avoir un bouton "Rechercher un dossier" et une zone de texte qui affiche le dossier spécifié.
La partie pour instruire l'exécution doit avoir un bouton «exécuter».
Pour la partie qui affiche la progression, le nom du fichier en cours de traitement est affiché dans la zone de texte et le taux de progression global est affiché dans la barre de progression.
Je pense que ce placement de pièce peut être facilement fait en utilisant un outil de conception graphique approprié, mais pour le moment, je l'écrirai à la main.
En gros, commencez par Premiers programmes dans 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('référence...')
hb1 = QHBoxLayout()
hb1.addWidget(self.txtFolder)
hb1.addWidget(self.btnFolder)
self.btnExec = QPushButton('Courir')
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)
C'est presque comme prévu.
Défini comme un événement cliqué dans btnFolder.
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
Ouvrez la boîte de dialogue de spécification du dossier et activez le bouton "Exécuter".
Collectez les fichiers ".py" dans le dossier spécifié et affichez le nom du fichier dans txtLog. De plus, la progression lors de l'exécution est représentée par une barre de progression.
guimain.py
from filelist import FileList
Modifiez légèrement la classe FileList par rapport à la version d'origine.
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()
alors,root_dir
Quandext
A été spécifié, mais il a été nouvellement définisetup()
Passez à la méthode.
Dans le programme GUI, puisque le tableau GUI s'exécute sur mutti-thread, la classe FileList est héritée de QThread de sorte que le tableau de fichiers fonctionne lui-même également sur multi-thread.
Il implémente également une fonction pour envoyer un signal afin que la barre de progression puisse être déplacée pour chaque processus.
À l'origine, dans process_file (), par exemple, s'il s'agit d'un fichier image, des retouches sont effectuées, mais dans cet exemple, ce n'est pas le point principal, donc je ne ferai rien pour le moment.
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) #transmission du signal
self.stop()
self.finished.emit() #transmission du signal
def retrieve(self):
''' root_Obtenez un fichier avec l'extension ext à partir de 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):
'''Ne rien faire pour le moment'''
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)
Si vous vous référez à cette classe FileList et appuyez sur le bouton, guimain.py qui analyse le dossier spécifié et affiche le processus est le suivant.
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('référence...')
self.btnFolder.clicked.connect(self.show_folder_dialog)
hb1 = QHBoxLayout()
hb1.addWidget(self.txtFolder)
hb1.addWidget(self.btnFolder)
self.btnExec = QPushButton('Courir')
self.btnExec.clicked.connect(self.exec_process)
self.btnExec.setEnabled(False)
self.btnExec.setVisible(True)
self.btnExit = QPushButton('Fin')
self.btnExit.setVisible(False) #Annulation
self.btnExit.setEnabled(False) #Ne montre pas
self.btnExit.clicked.connect(self.close)
hb2 = QHBoxLayout()
hb2.addWidget(self.btnExec)
hb2.addWidget(self.btnExit) #Ajout d'un bouton invisible à l'état initial
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) #Convertir le délimiteur de répertoire en fonction du système d'exploitation
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) #barre de progression
@pyqtSlot()
def finish_process(self):
self.fileList.wait()
#Masquer le bouton d'exécution
self.btnExec.setEnabled(False)
self.btnExec.setVisible(False)
#Afficher le bouton de fin
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)
Cela devient ennuyeux, donc si vous l'écrivez comme ci-dessus, cela fonctionnera pour le moment.
Dans FileList.run (), un signal est envoyé par `` self.sig_file.emit (fname) '' un par un, et en le recevant avec guimain.update_status (), la barre de progression s'affiche. Vous pouvez procéder un par un.
J'ai écrit une application GUI en Python. La clé est d'hériter de QThread.
Recommended Posts