Python 在PyQt中,在主窗口和线程之间共享数据的最佳方式是什么
我正在用PyQt4编写我的第一个GUI应用程序,我遇到了一个似乎非常基本的问题,但我似乎没有找到一个好的答案: 我使用一个线程连续执行一个重复的任务,而不阻塞主窗口。线程需要来自主窗口的一些信息(例如,spinbox的当前值),这些信息在线程运行时也会发生变化。在这种情况下,在主窗口和线程之间共享此类数据的正确方式是什么 天真地,我可以想出以下几种可能性:Python 在PyQt中,在主窗口和线程之间共享数据的最佳方式是什么,python,multithreading,qt,pyqt,Python,Multithreading,Qt,Pyqt,我正在用PyQt4编写我的第一个GUI应用程序,我遇到了一个似乎非常基本的问题,但我似乎没有找到一个好的答案: 我使用一个线程连续执行一个重复的任务,而不阻塞主窗口。线程需要来自主窗口的一些信息(例如,spinbox的当前值),这些信息在线程运行时也会发生变化。在这种情况下,在主窗口和线程之间共享此类数据的正确方式是什么 天真地,我可以想出以下几种可能性: 将对主机窗口的引用传递给线程,并使用它检索相关变量的当前值(请参见下面的示例) 在线程中保留变量的副本,并通过在变量更改时发出信号使其与主窗
从PyQt4导入QtGui,QtCore
导入时间,sys
类主窗口(QtGui.QWidget):
定义初始化(自):
超级(主窗口,自我)。\uuuu初始化
self.layout=QtGui.QVBoxLayout(self)
self.spinbox=QtGui.QSpinBox(self)
self.spinbox.setValue(1)
self.layout.addWidget(self.spinbox)
self.output=QtGui.QLCDNumber(self)
self.layout.addWidget(self.output)
self.worker=worker(self)
self.connect(self.worker、QtCore.SIGNAL('beep')、self.update)
self.worker.start()
def更新(自我,编号):
self.output.display(数字)
类工作程序(QtCore.QThread):
定义初始化(自,主机窗口):
超级(工作者,自我)。\uuuu初始化
self.host=host\u窗口
self.running=False
def运行(自):
self.running=True
i=0
自运行时:
i+=1
自我发射(QtCore.SIGNAL('beep'),i)
sleep\u time=self.host.spinbox.value()
时间。睡眠(睡眠时间)
def停止(自):
self.running=False
app=QtGui.QApplication(sys.argv)
窗口=主窗口()
window.show()
app.exec()
PS:因为我对PyQt完全没有经验,所以代码不太可能有其他问题,或者问题不清楚。在这种情况下,请随意评论或编辑问题。小部件不是线程安全的,请参阅: 尽管QObject是可重入的,但GUI类,尤其是QWidget和 它的所有子类都不是可重入的。它们只能从以下位置使用: 主线程 请参见此处的更多定义:
您应该只在主线程中使用小部件,并使用信号和插槽与其他线程通信 我不认为全局变量会起作用,但我真的不知道为什么
本例中如何使用信号:
#in main
self.worker = Worker(self.spinbox.value())
self.worker.beep.connect(self.update)
self.spinbox.valueChanged.connect(self.worker.update_value)
class Worker(QtCore.QThread):
beep=QtCore.pyqtSignal(int)
def __init__(self,sleep_time):
super(Worker, self).__init__()
self.running = False
self.sleep_time=sleep_time
def run(self):
self.running = True
i = 0
while self.running:
i += 1
self.beep.emit(i)
time.sleep(self.sleep_time)
def stop(self):
self.running = False
def update_value(self,value):
self.sleep_time=value
注意:我使用了新样式的信号和插槽尽管我给出了答案,但您的代码似乎工作正常,所以可能是我错了,或者有什么我不明白的地方。@tmoreau。在这种特殊情况下,工作线程只需从自旋框访问值。如果它试图更改该值,则更有可能导致问题(因为它可能导致GUI更新)。但是,调用
value()
仍然不是线程安全的,因为用户可以同时更改自旋框的值,而这些更改可能不是原子操作。即便如此,最糟糕的情况可能是工作线程可能会从spin-box中获得一个“过时”值。所以你是说不应该使用选项1和3。您能否给出一些提示,说明如何仅使用线程之间的信号来实现所需的行为?对我来说,这似乎是一个相当基本的任务的可怕的复杂性(至少当我处理许多我想分享的不同信息时)。嗯,我觉得使用线程从来都不是基本的。但我仍然感到惊讶的是,当我发现的每个文档都重复“不要从主线程以外的任何地方更改/访问小部件”时,上面的代码工作得非常好。不管怎样,请参见“编辑”中的信号示例。再次感谢您提供的其他示例!这看起来还不错。:)我仍然认为,在两个地方保存同一信息的两份副本对我来说似乎很奇怪,但这就是我现在所做的。我还修改了代码,以便在主线程中保留尽可能多的信息处理,这样我只需要在线程之间传递最少数量的值。