为了账号安全,请及时绑定邮箱和手机立即绑定

将信号连接到插槽会产生 (nullptr)::slot() 错误

将信号连接到插槽会产生 (nullptr)::slot() 错误

暮色呼如 2023-01-04 11:31:56
我想将来自自定义 QWidget 类 (WidgetClass) 的信号连接到 DerivedController 的插槽。我在实例化两个类后尝试连接信号。但是,我在 connect() 语句中收到以下错误:QObject::connect: Cannot connect WidgetClass::mySignal(double) to (nullptr)::mySlot(double)我不太清楚为什么会这样。如果我理解正确,您只能将信号连接到类实例之间的插槽。下面是我正在编写的伪实现(它在 ipython 中产生相同的错误):from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObjectfrom PyQt5.QtWidgets import QApplication, QWidgetclass BaseController():    def __init__(self, widget1, widget2):        self.widget1 = widget1        self.widget2 = widget2    #@pyqtSlot(float)    def mySlot(self, value):        print(f"BaseClass got {value}.")class DerivedController(BaseController):    def __init__(self, widget1, widget2):        super().__init__(widget1, widget2)    @pyqtSlot(float)    def mySlot(self, value):        #super().mySlot(value)        print(f"Derived class got {value}!")    def _setupConnections(self):        self.widget1.mySignal.connect(            self.mySlot)        self.widget2.mySignal.connect(            self.mySlot)class WidgetClass(QWidget):    mySignal = pyqtSignal(float)    def emitSignal(self):        self.mySignal.emit(1.8)def myfunc():    w1 = WidgetClass()    w2 = WidgetClass()    controller = DerivedController(w1, w2)    controller._setupConnections()    controller.widget1.emitSignal()def main():    app = QApplication(["test"])    return app.exec(myfunc())if __name__ == "__main__":    main()
查看完整描述

3 回答

?
HUX布斯

TA贡献1876条经验 获得超6个赞

OP提出的解决方案是不正确的,因为错误的原因是不同的:

如果您从类 P 继承,那么您必须调用类 P 的构造函数,在您的情况下,从 QObject 继承的 BaseController 不会调用 QObject 的构造函数。

综合以上,题目的报错信息不再获取,但还有其他问题:

  • 一个函数的作用域是有限的,在该函数内创建的对象在函数执行时被销毁,在这种情况下“控制器”被销毁,可能会导致问题。

  • 另一方面,QApplication exec() 方法不应接收任何参数。

综合以上,解决办法是:

from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject

from PyQt5.QtWidgets import QApplication, QWidget



class BaseController(QObject):

    def __init__(self, widget1, widget2):

        super().__init__()

        self.widget1 = widget1

        self.widget2 = widget2


    # @pyqtSlot(float)

    def mySlot(self, value):

        print(f"BaseClass got {value}.")



class DerivedController(BaseController):

    def __init__(self, widget1, widget2):

        super().__init__(widget1, widget2)


    @pyqtSlot(float)

    def mySlot(self, value):

        # super().mySlot(value)

        print(f"Derived class got {value}!")


    def _setupConnections(self):

        self.widget1.mySignal.connect(self.mySlot)

        self.widget2.mySignal.connect(self.mySlot)



class WidgetClass(QWidget):

    mySignal = pyqtSignal(float)


    def emitSignal(self):

        self.mySignal.emit(1.8)



def myfunc():

    w1 = WidgetClass()

    w2 = WidgetClass()

    controller = DerivedController(w1, w2)

    controller._setupConnections()

    controller.widget1.emitSignal()


    return controller



def main():

    app = QApplication(["test"])

    controller = myfunc()

    return app.exec()



if __name__ == "__main__":

    main()

另一方面,OP 在其回答中指出:我认为这是因为我们没有绑定到实例的插槽,但类本身的插槽是假的,连接是对象之间的。


查看完整回答
反对 回复 2023-01-04
?
墨色风雨

TA贡献1853条经验 获得超6个赞

你忘了super().__init__()打进来的电话BaseController



查看完整回答
反对 回复 2023-01-04
?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

我发现以下部分是错误的:

self.widget1.mySignal.connect(
    self.mySlot)
self.widget2.mySignal.connect(
    self.mySlot)

并且应该这样重写:

self.widget1.mySignal.connect(
    DerivedController.mySlot)
self.widget2.mySignal.connect(
    DerivedController.mySlot)

这似乎解决了这个问题。我认为这是因为我们没有绑定到实例的插槽,而是绑定到类本身的插槽,就像声明为类定义的一部分的信号一样,而不是类实例化(我希望这是有道理的)。


查看完整回答
反对 回复 2023-01-04
  • 3 回答
  • 0 关注
  • 142 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号