如何在Qt connect中将QObject作为参数从信号传递到槽函数

9
我的原始代码通过信号将QStringList传递给槽函数,然后返回一个QList。一切都运行正常,但是我需要将QStringList和QList都改为两个不同的子类化QObjects。自那时以来,我一直收到诸如“合成方法首次在此处需要”之类的错误,或者简单地崩溃而没有任何错误消息。
我知道qt会复制在排队连接中传递的所有参数,并且QObject无法被复制。因此,我想在发射信号之前创建这两个QObjects。然后,我将传递对每个对象的引用,在槽函数中修改其中一个对象,并且不返回任何值。
不幸的是,无论我如何编写信号和槽函数,应用程序仍然崩溃。
我应该如何编写信号/槽函数并将它们连接起来,以便传递两个qobjects作为参数或返回一个qobject?
MyQObject1 obj1("a","b","c");
MyQObject2 obj2();
emit sendSignal(&obj1, &obj2);
// or
MyQObject2 obj2 = emit sendSignal(&obj1);

connect(someObj, SIGNAL(sendSignal(const QObject&)), this, SLOT(receiveSignal(const QObject&)));

receiveSignal()函数不直接创建或修改任何QObject。
它必须首先将QObjects传递给另一个函数,该函数然后要么修改obj2,要么创建并返回它。
非常感谢任何代码示例。
1个回答

12

通常情况下,传递QObject时使用指针而不是引用(请注意,QObject无法复制并且无法按值传递)。QObject*默认已注册为元类型。因此,创建具有QObject*参数的信号和槽就足以使它们正常工作:

private slots:
  void test_slot(QObject* object);

signals:
  void test_signal(QObject* object);

初始化:

connect(this, SIGNAL(test_signal(QObject*)), this, SLOT(test_slot(QObject*)));

发出:

QObject* object = new QObject();
emit test_signal(object);

当然,信号和槽可以在不同的类中。


1
除非连接是queued,否则您不需要为signal/slot进行任何元类型注册。而对于排队的连接,我会看到与object所有权相关的问题。谁拥有它并将再次删除它?发射器?何时? - Frank Osterfeld
QObject* 是一种通用的元类型。它默认注册,并被一些内置信号(例如 destroyed)使用。排队连接也可以在没有注册的情况下工作。QObject 的所有权是通过设置其父对象来声明的(除非它是在堆栈上创建的)。通过指针传递它通常不会导致所有权问题,并且在 Qt API 中广泛使用。通常,在 API 中有约定告诉我们当调用方法(槽)时所有权发生了什么。 - Pavel Strakhov
元类型:我知道这点,但这不是我的重点。你说 QObject* 被注册为元类型,因此可以在信号槽中使用它。但这并非强制要求;如果是的话,传递 MyObjectSubclass* 的参数将在未将 MyObjectSubclass* 也注册为元类型的情况下失败。 - Frank Osterfeld
1
所有权:问题在于父/子所有权对信号/槽没有帮助,特别是对于排队连接。因此,仅仅为了通过信号发送它们而动态创建QObjects并不是常见的做法,有很好的理由。接收者不能拥有该对象,因为可以有任意多个接收者或根本没有接收者。在发送器中,如果每次发出test_signal()时都创建另一个对象,它们将堆叠起来,除非发送器立即删除它们(但在排队连接中使用时指针将会悬空)。 - Frank Osterfeld
1
如果您正在使用排队连接,并且接收器可能会比发送器存在更长的时间,那么它也无法删除对象。因此,在某些情况下,通过共享指针管理对象并传递QSharedPointer<MyQObjectSubclass>可能是最好的解决方法。或者,不要使用信号/槽来解决问题,这看起来是错误的应用。 - Frank Osterfeld
显示剩余2条评论

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