PyQt5信号插槽无法正常工作

时间:2017-05-28 14:59:23

标签: python qt pyqt pyqt5 signals-slots

首先,这是我的代码:

class PyQtObject(object):
    class __PyQtObject(QObject):
        my_signal = pyqtSignal()

        def __init__(self):
            QObject.__init__(self)
            self.my_signal.connect(self.my_slot)

        @pyqtSlot()
        def my_slot(self):
            print("call")

        def call_in_main_thread(self):
            print("should call")
            print(self)
            self.my_signal.emit()

    instance = None

    def __init__(self):
        if PyQtObject.instance is None:
            PyQtObject.instance = PyQtObject.__PyQtObject()

    def __getattr__(self, name):
        return getattr(self.instance, name)

这就是它应该如何运作:

我正在创建一个带有文本框的PyQt窗口,该窗口接收另一个线程的频繁更新,为其添加行。 这导致输出不稳定,因为QWidgets的元素不应在PyQt主线外更改 您可以通过发出信号来解决这个问题,该信号连接到一个插槽,然后将这些行添加到文本字段中。

现在当你在很多地方都有这样的设置时,它对我有意义,将它外包给一个发出信号的功能,并从插槽中调用该功能。上面的代码是我想出来的。

现在问题是,这是结果输出:

should call
<object at ...ABCDEF>
call
should call
<object at ...ABCDEF>
...
should call
<object at ...ABCDEF>
call

如您所见,插槽仅偶尔调用。我可以完全计算3个电话,直到它完全停止被呼叫。除了第一个呼叫之外,这三个呼叫在它们之前有很多信号发射。打印对象以确保在调用插槽之前不会对内存变量进行内存清理。

这里出了什么问题?我测试过的事情:

  • 将插槽重新连接到信号不会改变任何内容。
  • 在各个地方添加多线程并没有改变任何内容。
  • 单身人士模式。

我真的很茫然

更新我尝试了一种有两种选择的新方法:

caller_objects = []

class CallerObject(QObject):
    signal = pyqtSignal()

    def __init__(self, func: callable, args: tuple = None, kwargs: dict = None):
        import threading

        QObject.__init__(self)
        self.func = func
        self.args = args
        self.kwargs = kwargs
        self.signal.connect(self.slot)

        # option 1
        self.signal.emit()
        # option 2
        threading.Thread(target=self.signal.emit).start()

    @pyqtSlot()
    def slot(self):
        print("call")
        global caller_objects
        if self.kwargs is not None:
            if self.args is not None:
                self.func(*self.args, **self.kwargs)
            else:
                self.func(**self.kwargs)
        elif self.args is not None:
            self.func(*self.args)
        else:
            self.func()
        caller_objects.remove(self)


def call_in_main_thread(func: callable, args: tuple = None, kwargs: dict = None):
    global caller_objects
    caller_objects.append(CallerObject(func, args, kwargs))

选项1导致即时不可捕获的崩溃 选项2导致插槽被称为有时。我几乎不知道何时或为什么,但是当我在GUI中点击时有时会被调用。在日志中添加行call

太奇怪了

0 个答案:

没有答案