2016-11-13 7 views
2

Я пишу простой сценарий для изменения размера фотографий. Я хотел бы иметь виджет с текстовым полем, в котором появляются сообщения после изменения размера каждого файла.Режимы реального времени в реальном времени

#!/usr/bin/python3 
# -*- coding: utf-8 -*- 

import time, sys 
from PyQt5.QtCore import pyqtSignal, QThread 
from PyQt5.QtWidgets import QApplication, QPushButton, QTextEdit, QWidget, QVBoxLayout 

class Thread(QThread): 
    log = pyqtSignal(str) 
    def __init__(self, parent=None): 
     super(Thread, self).__init__(parent) 
    def test(self, i): 
     time.sleep(1) 
     self.log.emit(str(i)) 

class Widget(QWidget): 
    def __init__(self): 
     super().__init__() 
     self.ui() 
    def process(self): 
     self.toLog('some text...') 
     worker = Thread() 
     worker.log.connect(self.toLog) 
     for i in range(1, 5): 
      worker.test(i) 
    def ui(self): 
     self.LogOutputTxt = QTextEdit() 
     self.LogOutputTxt.setReadOnly(True) 
     startBtn = QPushButton('Start') 
     startBtn.clicked.connect(self.start) 
     layout = QVBoxLayout() 
     layout.addWidget(self.LogOutputTxt) 
     layout.addWidget(startBtn) 
     self.setLayout(layout) 
     self.resize(400, 300) 
     self.show() 
    def start(self): 
     self.toLog('start') 
     self.process() 
    def toLog(self, txt): 
     self.LogOutputTxt.append(txt) 

if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    ui = Widget() 
    sys.exit(app.exec_()) 

Пока все сообщения появляются сразу после изменения всех файлов. Есть ли способ сделать это один за другим (я имею в виду размер файла, отображаемое сообщение и т. Д.)?

+0

Код, который вы опубликовали, является неполным и неправильным во многих отношениях, что его очень сложно переписать его конструктивно. Пожалуйста, прочитайте руководство по изготовлению [mcve]. – ekhumoro

+0

Извините, я переписал код, надеюсь, что сейчас лучше. – przemekk

+0

Ожидаете ли вы, что эти рабочие потоки выполняются одновременно? Если они выполняют код python, который связан с cpu (например, изменение размеров изображений), только один из них может запускаться за раз (из-за блокировки Global Interpreter Lock). Для параллельной обработки вам нужно будет использовать отдельные процессы, а не потоки. – ekhumoro

ответ

2

Ниже приведена перезапись вашего сценария, который должен делать то, что вы хотите.

Обратите внимание, что это довольно упрощенно и не требует слишком больших усилий для обеспечения безопасности потоков. Метод setItems просто делает неглубокую копию переданных ему данных, что действительно реально для списка неизменяемых объектов. Вы также должны убедиться, что в рабочем потоке никогда не выполняете никаких операций gui, которые включают операции с изображениями. Если вы хотите манипулировать изображениями, используйте QImage. (И если вы хотите знать, как остановить текущий поток, см., Например, this answer).

#!/usr/bin/python3 
# -*- coding: utf-8 -*- 

import time, sys 
from PyQt5.QtCore import pyqtSignal, QThread 
from PyQt5.QtWidgets import (
    QApplication, QPushButton, QTextEdit, QWidget, QVBoxLayout 
    ) 

class Thread(QThread): 
    log = pyqtSignal(str) 

    def __init__(self, parent=None): 
     super(Thread, self).__init__(parent) 
     self._items = [] 

    def setItems(self, items): 
     if not self.isRunning(): 
      self._items[:] = items 

    def run(self): 
     for item in self._items: 
      time.sleep(1) 
      self.log.emit('processing: %s' % item) 

class Widget(QWidget): 
    def __init__(self): 
     super().__init__() 
     self.ui() 
     self._worker = Thread(self) 
     self._worker.log.connect(self.toLog) 
     self._worker.started.connect(lambda: self.toLog('start')) 
     self._worker.finished.connect(lambda: self.toLog('finished')) 

    def process(self): 
     items = ['Image%02d.png' % i for i in range(10)] 
     self._worker.setItems(items) 
     self._worker.start() 

    def ui(self): 
     self.LogOutputTxt = QTextEdit() 
     self.LogOutputTxt.setReadOnly(True) 
     startBtn = QPushButton('Start') 
     startBtn.clicked.connect(self.start) 
     layout = QVBoxLayout() 
     layout.addWidget(self.LogOutputTxt) 
     layout.addWidget(startBtn) 
     self.setLayout(layout) 
     self.resize(400, 300) 
     self.show() 

    def start(self): 
     if not self._worker.isRunning(): 
      self.process() 

    def toLog(self, txt): 
     self.LogOutputTxt.append(txt) 

if __name__ == '__main__': 

    app = QApplication(sys.argv) 
    ui = Widget() 
    sys.exit(app.exec_()) 
+0

Спасибо за ваш ответ :-). Мне кажется достаточно. Вначале я написал простой командный командный скрипт с использованием PIL для обработки изображений, я пытался создать графический интерфейс только из любопытства, поэтому упрощенное решение действительно в порядке. – przemekk