問題描述
我正在編寫一個用于調整照片大小的簡單腳本.我想要一個帶有文本字段的小部件,在調整每個文件大小后會在其中顯示消息.
I'm writing a simple script for resizing photos. I'd like to have a widget with text-field in which messages appear after resizing each file.
#!/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_())
到目前為止,在調整所有文件大小后,所有消息都會立即顯示.有沒有辦法一一做到(我的意思是文件大小調整、消息顯示等)?
So far all the messages appear at once after all files are resized. Is there any way to do it one by one (I mean file resized, message displayed, etc.)?
推薦答案
下面是你想要的腳本的重寫.
Below is a re-write of your script that should do want you want.
但請注意,這非常簡單,并且不會太努力地確保線程安全.setItems
方法只是制作傳遞給它的數據的淺表副本 - 這僅適用于不可變對象列表.您還必須確保您永遠不會在工作線程中執行任何 gui 操作,其中包括對像素圖的操作.如果要操作圖像,請使用 QImage
.(如果您想知道如何停止正在運行的線程,請參閱例如 this answer).
But note that this is quite simplistic, and doesn't try too hard to ensure thread-safety. The setItems
method just makes a shallow copy of the data passed to it - which is only really okay for a list of immutable objects. You also must make sure you never do any gui operations inside the worker thread, which includes operations on pixmaps. If you want to manipulate images, use QImage
. (And if you want to know how to stop a running thread, see for example 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_())
這篇關于線程實時記錄的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!