在另一个类中无法连接信号到槽函数。

7
我是一个有用的助手,可以为您翻译文本。
我有两个类:A类和B类。我正在从A类发出信号,希望B类能够接收到。
我按照以下方式进行操作:
在监听器文件中:
Header File:
  Class Listener:public DDSDataReaderListener
  {
     //Some code
    public:
       A m_objectSendData;
  }

实现文件:

  void Listener::ondataavailable(DDSDataReader *reader)
 {
  m_objSendData.GetDDSData();
 }

在A类中 头文件:
Class A:public QObject
{
  Q_OBJECT
  public:
    void GetDDSData();
  signals:
    void Signal_Data();
}

.cpp文件

 A::A(QWidget *parent):QObject(parent)
{
}

void A::GetDDSData()
 {
   emit Signal_Data();
 }   

在B类中

Header File:

  Class B:public QObject
  {
    Q_Object
    public:
    A objGetData;

    public slots:
    void getData();
  }

Implementation File:

 B::B(QWidget *parent):QObject(parent)
{
   //Some part of code

  connect(&objGetData,SIGNAL(Signal_Data()),this,SLOT(getData());
 }

 void B::getData()
 {
    //Watever is to be updated
  }

我尝试进行调试。它已经正确执行了发出部分,但是没有到达插槽。 有人可以帮助我吗? 谢谢。


在运行您的应用程序时,您是否收到任何像Object::connect: No such slot B :: SlotB()这样的消息? - thuga
没有显示任何这样的消息。 - Sid411
除了您的“connect”语句中缺少分号前的“)”之外,我在您上面发布的代码中看不出任何问题,但显然这在您的实际代码中并没有缺失。 - thuga
检查布尔值connect的返回值。如果它是true,那么连接成功了,你就不需要发出信号。如果它返回false,那么请检查@Merlin069给你的答案。 - Marek R
2
还有一件事,你没有展示足够的代码,但我怀疑你的程序留下了objectA变量的空间,而且你发出的对象在发出任何信号之前就被销毁了(objectA是在堆栈上创建的局部变量,而不是在堆上)。 - Marek R
可能是C++ Qt信号和槽未触发的重复问题。 - László Papp
2个回答

16

没有完整的代码,很难确定问题的确切问题,因此我将概述一些重要点进行检查。

为确保您可以使用信号和插槽机制,您应该确保您的类派生自QObject或其继承层次结构中已经派生自QObject的类,并且您的类必须包含Q_OBJECT宏,例如: -

class A : public QObject // derived from QObject
{
    Q_OBJECT // your class must have this macro for signals and slots

    public:
    A();
};
省略宏可能是最常见的错误之一。
要指定一个插槽,您需要将其添加到类的公共或私有插槽部分中:-
class B : public QObject // derived from QObject
{
    Q_OBJECT // your class must have this macro for signals and slots

    public:
    B();

    public slots:
        void SlotB(); // slot declared public

    private slots:
        void SlotBPrivate(); // slot declared private.
}; 

一旦在类中声明了一个信号,接收该信号的槽应与传递的参数匹配。当您将信号连接到槽时,不得添加函数参数名称。

因此:-

connect(&objectA, SIGNAL(SignalA(int in), this, SIGNAL(SlotA(int param)); //will fail due to the argument names

应该是:-

connect(&objectA, SIGNAL(SignalA(int), this, SIGNAL(SlotA(int));

最后,如果你正在使用Qt 5,你可以使用新的连接调用方式,它不需要你指定任何参数,而是取代传统方式采用槽函数和信号函数的地址。

connect(&objectA, &A::SignalA, this, &B::SlotA));

由于它引用了函数的地址,实际上,这些函数不需要被归类为插槽(slot),但仍然会被调用。

希望这有所帮助。


1
我已经按照完全相同的方式做了。但我仍然不明白问题出在哪里。我的函数和槽都是公共的。 - Sid411
那么,您能否在问题中添加更多代码,例如声明插槽和信号的头文件。另请注意,当您使用调试器运行应用程序并且连接调用失败时,输出窗口会显示错误。请也发布该错误信息。 - TheDarkKnight
我会向您解释我正在做的整个情况。我有一个DDS监听器,从那里我调用QT函数。从这个函数中,我发出一个信号,该信号进入我的主线程插槽。在这里,我更新来自DDS的值。我已经包含了所有的头文件,代码中没有太多需要编写的内容。它就像我写的一样。唯一的补充是,在我的监听器中,我创建了一个类A的对象并调用了该函数。这是我在监听器中所做的唯一事情。 在调试时,它显示停在断点三处,即连接语句处。 - Sid411
很抱歉,虽然您说已经包含了所有的代码,但是显然没有类的定义,没有Q_OBJECT宏,没有信号或槽标签等。虽然您可能认为已经提供了所有必要的信息,但这对我们来说还不够。与其让您的问题陈述为“在A类中...”,您需要向我们展示代码以便我们理解其上下文并帮助您解决问题。我可以向您展示代码“a = 4”并告诉您它正在崩溃,但是如果您不知道'a'是什么以及它周围的代码,您就不知道原因。 - TheDarkKnight
我认为你的示例中有几个错误:你两次显示了 SIGNAL() 而不是 SIGNAL()SLOT();此外,打开和关闭的括号数量不匹配。这绝对是为什么 Qt5 信号更好(在我看来),因为任何类型的错误很可能会在编译时被捕获。 - Alexis Wilke

1

实际上,我相信其中一个评论给出了答案。

还有一件事,你没有展示足够的代码,但我怀疑你的程序离开了ObjectA变量的范围,并且在它发出任何信号之前,你的发射器对象就被销毁了(ObjectA是在堆栈上创建的局部变量而不是在堆上创建的)。- Marek R 1小时前

所以,你在堆栈上分配了你的对象,因此它会在超出作用域时被销毁,同时与所有其连接到的信号/插槽断开连接。

这就是为什么你不会看到任何错误/警告消息的原因,因为代码本身完全合法。你应该使用new()来分配你的对象,使其在堆上分配。


我将其用作成员变量,但它无法正常工作。因此,在这种情况下,它应该进入堆。我将编辑并编写完整的代码。 - Sid411
我认为问题在于我的中间类不是单例类。我将尝试将其制作为单例类,然后在此处编辑解决方案... - Sid411

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接