【问题标题】:How to connect functions to PyQt signals outside of main thread如何将函数连接到主线程外的 PyQt 信号
【发布时间】:2018-12-11 18:41:33
【问题描述】:

我正在创建一个 PyQt 应用程序,我希望有一个后台线程连接一些事件处理程序,然后永远循环直到主窗口关闭。我遇到的问题是,我连接的事件处理程序只有在它们是在我的 MainWindow 类中定义的函数时才起作用。我在下面创建了一个最小的复制:

import threading
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton, QVBoxLayout


class MainWindow(QDialog):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.button1 = QPushButton("Click Me", self)
        self.button2 = QPushButton("Me Too!", self)

        layout = QVBoxLayout()
        layout.addWidget(self.button1)
        layout.addWidget(self.button2)
        self.setLayout(layout)

    def test(self):
        print("test inside class")


def test2():
    print("test outside class")


def main(window):
    window.button1.clicked.connect(window.test)
    window.button2.clicked.connect(test2)
    # Loop that runs in thread...


app = QApplication([])
window = MainWindow()
window.show()
threading.Thread(target=main, args=[window]).start()
app.exec_()

当我运行此代码时,第一个按钮按预期向控制台打印一条消息,但第二个按钮在单击时什么也不做。如果我在主线程中运行main(window) 函数,那么两个按钮都可以工作。我知道在我的小示例程序中,这将是显而易见的解决方案,但由于复杂的原因,我需要能够从我的应用程序的后台线程连接事件处理程序。为什么当我在主线程之外进行连接时,在MainWindow 类之外定义的test2() 之类的函数不起作用?

【问题讨论】:

    标签: python multithreading pyqt pyqt5


    【解决方案1】:

    我仍在找出问题的原因,但解决方案是指出连接的类型,在这种情况下 Qt::DirectConnection 将使函数 test2 在发出信号的对象的同一线程上运行(发出信号的对象是位于主线程中的按钮)。

    import threading
    from PyQt5 import QtCore, QtWidgets
    
    class MainWindow(QtWidgets.QDialog):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.button1 = QtWidgets.QPushButton("Click Me")
            self.button2 = QtWidgets.QPushButton("Me Too!")
            layout = QtWidgets.QVBoxLayout(self)
            layout.addWidget(self.button1)
            layout.addWidget(self.button2)
    
        @QtCore.pyqtSlot()
        def test(self):
            print("test inside class")
    
    def test2():
        print("test outside class")
    
    def main(window):
        window.button1.clicked.connect(window.test)
        window.button2.clicked.connect(test2, QtCore.Qt.DirectConnection)
        while True:
            QtCore.QThread.sleep(1)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        window = MainWindow()
        window.show()
        threading.Thread(target=main, args=(window,), daemon=True).start()
        sys.exit(app.exec_())
    

    【讨论】:

    • 谢谢,使用Qt.DirectConnection 解决了这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 2012-03-28
    • 2017-11-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    相关资源
    最近更新 更多