【发布时间】:2015-04-14 12:10:49
【问题描述】:
您好 StackExchange 社区,
首先,你们对我帮助很大,非常感谢。第一次提问:
我目前正在编写一个 PyQt GUI 应用程序,我发现它在 Windows 系统上崩溃,而且它在我家的机器上给我一个段错误,而它在工作的机器上工作(都是 linux mint 17)。经过一番研究,我意识到我可能创建了一个线程不安全的 GUI,因为我有几个对象相互调用方法。
From another stackoverflow question: GUI 小部件只能从主线程访问,即调用 QApplication.exec() 的线程。从任何其他线程访问 GUI 小部件——你对 self.parent() 的调用——是未定义的行为,在你的情况下这意味着崩溃。
From Qt docs: 虽然 QObject 是可重入的,但 GUI 类,尤其是 QWidget 及其所有子类,是不可重入的。它们只能在主线程中使用。如前所述,还必须从该线程调用 QCoreApplication::exec()。
所以最后,我认为我应该只使用信号槽系统来这样做。
- 这是正确的吗?
- 这只是函数调用需要,还是我可以在运行时以线程安全的方式操作来自其他对象的某些对象的字段?例如,我有一个可以从多个其他对象访问的选项对象,并且我经常从不同的来源更改参数。线程安全还是不安全?
接下来,我在示例代码中重新创建这种线程不安全行为时遇到了问题。 Qt 文档说 QObjects 存在于不同的线程中。这意味着,以下 Qt 应用程序应该是线程不安全的(如果我理解正确的话)。
from PyQt4 import QtGui
import sys
class TestWidget(QtGui.QWidget):
def __init__(self,string):
super(TestWidget,self).__init__()
self.button = QtGui.QPushButton(string,parent=self)
self.button.clicked.connect(self.buttonClicked)
# just to check, and yes, lives in it's own thread
print self.thread()
def buttonClicked(self):
# the seemingly problematic line
self.parent().parent().statusBar().showMessage(self.button.text())
pass
pass
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow,self).__init__()
Layout = QtGui.QHBoxLayout()
for string in ['foo','bar']:
Layout.addWidget(TestWidget(string))
CentralWidget = QtGui.QWidget(self)
CentralWidget.setLayout(Layout)
self.setCentralWidget(CentralWidget)
self.statusBar()
self.show()
pass
pass
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
M = MainWindow()
sys.exit(app.exec_())
但它可以在我的机器上运行,也可以在 Windows 机器上正常运行。
- 为什么?这实际上是线程不安全的并且可能会崩溃,但它不会吗?
感谢您帮我解决这个问题...
【问题讨论】:
标签: python multithreading qt pyqt4