【问题标题】:Connecting a signal to slot yields (nullptr)::slot() error将信号连接到插槽会产生 (nullptr)::slot() 错误
【发布时间】:2020-09-29 03:09:37
【问题描述】:

我想将来自我的自定义 QWidget 类 (WidgetClass) 的信号连接到 DerivedController 的插槽。 我在实例化两个类后尝试连接信号。

但是,我在 connect() 语句中收到以下错误:

QObject::connect: Cannot connect WidgetClass::mySignal(double) to (nullptr)::mySlot(double)

我不太清楚为什么会这样。如果我理解正确,您只能将信号连接到类实例之间的插槽。 下面是我正在编写的伪实现(它在 ipython 中产生相同的错误):

from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
from PyQt5.QtWidgets import QApplication, QWidget

class 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()

【问题讨论】:

    标签: python pyqt5 qt5 signals


    【解决方案1】:

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

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

    并且应该这样改写:

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

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

    【讨论】:

      【解决方案2】:

      由于错误原因不同,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 在其回答中指出:我认为这是因为我们没有绑定到实例的插槽,但类本身的插槽是错误的,对象之间的连接。

      【讨论】:

      • 我已经简化了示例代码。控制器实例实际上是另一个类 (QDialog) 的成员,在我的例子中它永远不会超出范围。
      【解决方案3】:

      您忘记了BaseController 中的super().__init__() 呼叫

      【讨论】:

      • 在我的实际程序中,我实际上并没有从QObject继承,它是一个从“object”继承的基本python类。因此犯了错误。
      • 您需要从 QObject 继承才能使用 Signals。你的问题解决了吗?
      • 谢谢,我相信这是真正的问题。我的问题解决了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-15
      • 1970-01-01
      相关资源
      最近更新 更多