【问题标题】:Statusbar doesn't show message immediately and sometimes crash状态栏不会立即显示消息,有时会崩溃
【发布时间】:2015-05-12 10:03:06
【问题描述】:

我在pyqt4设计器中创建了一个界面,只有一个按钮和一个状态栏。单击按钮时,我想在状态栏中显示一条消息。出于某种原因,我必须将此操作放在一个新线程中。

但是当我点击按钮时,什么也没发生。直到我拖动窗口的边缘,该消息才出现。有时点击动作甚至会导致程序崩溃:

pythonw.exe has stopped working.

这种情况经常发生,尤其是当我点击太快时。

这是我的代码:

from PyQt4 import QtCore, QtGui
import threading

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):

    def cal(self):
        self.statusbar.showMessage('something')   

    def onbutton(self):

        thread = threading.Thread(target=self.cal)
        thread.start()



    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(510, 409)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.pushButton = QtGui.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(170, 100, 171, 91))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))
        self.pushButton.clicked.connect(self.onbutton)

        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.pushButton.setText(_translate("MainWindow", "PushButton", None))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

【问题讨论】:

  • 大多数 Qt 对象不能从工作线程更新,只能从主线程更新。根据您的描述,我认为 QStatusBar 就是这样一个对象。因此,您必须安排在工作线程想要显示消息时通知主线程。如何做到这一点取决于您的应用程序,但您应该查看 QCoreApplication.postEvent 和 QThread。

标签: python multithreading pyqt4


【解决方案1】:

发生崩溃是因为您从辅助线程与 Qt GUI 交互。您只能从主线程与 GUI 交互(参见Qt documentation)。

你有两个选择:

  1. 切换到 PyQt QThread,并从线程发出信号。如果信号连接到主线程中的插槽,那么您可以在那里进行 GUI 交互。这个question/answer 大致演示了如何做到这一点。

  2. 使用QApplication.postEvent() 将事件从 Python 线程发送到主线程,然后会导致运行与 GUI 交互的方法。请注意,有些人担心这不好(请参阅this SO Answer),但我对此没有任何意见。我已经将它封装在一个名为qtutils(文档here)的免费库中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    相关资源
    最近更新 更多