2016-11-13 98 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

您是否期望這些工作線程同時運行?如果他們正在執行cpu-bound的python代碼(如調整圖像大小),則一次只能運行其中的一個(因爲全局解釋器鎖定)。對於並行處理,您需要使用單獨的進程,而不是線程。 – 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編寫了簡單的命令批處理腳本以用於圖像處理,但我試圖僅以好奇心創建GUI,因此簡單化的解決方案確實很好。 – przemekk