PyQt 更新界面 [英] PyQt update gui
问题描述
我正在尝试通过 PyQt 中的 QThread
更新 Qt GUI 对象中的文本,但我收到错误 QPixmap:在 GUI 线程之外使用像素图是不安全的
,然后它崩溃了.我真的很感激任何帮助,谢谢.
I'm trying to update the text in a Qt GUI object via a QThread
in PyQt but I just get the error QPixmap: It is not safe to use pixmaps outside the GUI thread
, then it crashes. I would really appreciate any help, thanks.
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent = None):
QMainWindow.__init__(self, parent)
self.setupUi(self)
self.output = Output()
def __del__ (self):
self.ui = None
@pyqtSignature("")
def on_goBtn_released(self):
threadnum = 1
#start threads
for x in xrange(threadnum):
thread = TheThread()
thread.start()
class Output(QWidget, Ui_Output):
def __init__(self, parent = None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.ui = Ui_Output
self.show()
def main(self):
self.textBrowser.append("sdgsdgsgsg dsgdsg dsgds gsdf")
class TheThread(QtCore.QThread):
trigger = pyqtSignal()
def __init__(self):
QtCore.QThread.__init__(self)
def __del__(self):
self.wait()
def run(self):
self.trigger.connect(Output().main())
self.trigger.emit()
推荐答案
self.trigger.connect(Output().main())
这条线有问题.您正在线程中实例化一个看起来像小部件的类.这是错误的.您不应该在不同的线程中使用 GUI 元素.所有与 GUI 相关的代码都应该与事件循环在同一线程中运行.
This line is problematic. You are instantiating a class in the thread which looks like a widget. This is wrong. You shouldn't use GUI elements in a different thread. All GUI related code should run in the same thread with the event loop.
上面这行在设计上也是错误的.您从线程发出自定义信号,这是一个好方法.但是处理这个信号的对象应该是拥有/创建线程的对象,即你的MainWindow
The above line is also wrong in terms of design. You emit a custom signal from your thread and this is a good way. But the object to process this signal should be the one that owns/creates the thread, namely your MainWindow
您也不保留对线程实例的引用.您在方法中创建它,但它是本地的.所以它会被垃圾收集,你可能会看到一个警告,它在完成之前被删除了.
You also don't keep a reference to your thread instance. You create it in a method, but it is local. So it'll be garbage collected, you probably would see a warning that it is deleted before it is finished.
这是一个最小的工作示例:
Here is a minimal working example:
import sys
from PyQt4 import QtGui, QtCore
import time
import random
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
def setup(self, thread_no):
self.thread_no = thread_no
def run(self):
time.sleep(random.random()*5) # random sleep to imitate working
self.trigger.emit(self.thread_no)
class Main(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.text_area = QtGui.QTextBrowser()
self.thread_button = QtGui.QPushButton('Start threads')
self.thread_button.clicked.connect(self.start_threads)
central_widget = QtGui.QWidget()
central_layout = QtGui.QHBoxLayout()
central_layout.addWidget(self.text_area)
central_layout.addWidget(self.thread_button)
central_widget.setLayout(central_layout)
self.setCentralWidget(central_widget)
def start_threads(self):
self.threads = [] # this will keep a reference to threads
for i in range(10):
thread = MyThread(self) # create a thread
thread.trigger.connect(self.update_text) # connect to it's signal
thread.setup(i) # just setting up a parameter
thread.start() # start the thread
self.threads.append(thread) # keep a reference
def update_text(self, thread_no):
self.text_area.append('thread # %d finished' % thread_no)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainwindow = Main()
mainwindow.show()
sys.exit(app.exec_())
这篇关于PyQt 更新界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!