Как подключить функции к сигналам PyQt вне основного потока - PullRequest
0 голосов
/ 11 декабря 2018

Я создаю приложение 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) в главном потоке, то обе кнопки работают.Я знаю, что в моем небольшом примере программы это было бы очевидным решением, но по причинам, которые сложно объяснить, мне нужно иметь возможность подключать обработчики событий из фонового потока в моем приложении.Почему подключение такой функции, как test2(), которая определена вне класса MainWindow, не работает, когда я делаю это вне основного потока?

1 Ответ

0 голосов
/ 11 декабря 2018

Я все еще выясняю причину проблемы, но решение состоит в том, чтобы указать тип соединения, в данном случае 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_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...