【问题标题】:Connect all of an objects signals to a single slot将所有对象信号连接到单个插槽
【发布时间】:2012-04-11 05:08:16
【问题描述】:

环顾四周,人们似乎也遇到了类似的问题,但有来自不同来源的多个信号等。我的情况是,我有一个对象可以指示它是否成功、失败或被取消。这些信号被传递给另一个类,并且没有连接到插槽,只是一个信号。现在我想解决这个问题,无论对象发送什么信号(失败、成功、取消),都会调用一个槽来删除对象。简而言之,我想要一种将对象的每个信号都连接到插槽的方法。

想做这样的事情:

connect(myObject, allSignals, this, handleObjectDone());

void handleObjectDone() {
    myObject->deleteLater();
}

有没有办法做到这一点?或者我应该在每次它做某事时传递两个信号,例如emit readyToBeDeleted()emit succeded()

谢谢!

【问题讨论】:

  • 你想删除从连接槽发出信号的对象吗?
  • 我想从一个对象中捕获任何信号以便能够知道何时删除它
  • 你不能使用 deleteLater() 吗?
  • deleteLater 删除范围末尾的某些内容。我必须等到这些请求准备就绪后才能使用 delete later 删除它们

标签: c++ qt signals-slots


【解决方案1】:

抛开关于将一个对象中的所有信号连接到另一个对象中的单个插槽是否实际上是明智之举的任何疑虑,下面是一个可以做到这一点的函数,以及一个单元测试来验证它是否有效。

如果您在运行此程序时观看 stdout,您会看到它打印出所有正在建立的连接。当它运行时,点击 QLineEdit 将导致 QLineEdit 发出一个信号,这将(当然)导致 QApplication::quit() 槽被调用,因此应用程序将退出。

#include <stdio.h>
#include <QApplication>
#include <QLineEdit>
#include <QMetaMethod>
#include <QMetaObject>

void ConnectAllSignalsToSlot(QObject * sourceObject, QObject * targetObject, const char * slotName)
{
   const QMetaObject * mo = sourceObject->metaObject();
   if (mo)
   {
      int numMethods = mo->methodCount();
      int firstMethod = mo->methodOffset();  // set to 0 instead if you want to connect signals from superclasses too
      for (int i=firstMethod; i<numMethods; i++)
      {
         QMetaMethod mm = mo->method(i);
         if (mm.methodType() == QMetaMethod::Signal)
         {
            QString signalString = QString("2") + mm.signature();
            printf("Connecting up signal [%s] on object %p to slot [%s] on object %p\n", signalString.toUtf8().constData(), sourceObject, slotName, targetObject);  // just so we can see what it's doing
            QObject::connect(sourceObject, signalString.toUtf8().constData(), targetObject, slotName);
         }
      }
   }
   else printf("Error, sourceObject has no QMetaObject????\n");
}

int main(int argc, char ** argv)
{
   QApplication app(argc, argv);

   QWidget * testSource = new QLineEdit;
   testSource->show();

   ConnectAllSignalsToSlot(testSource, &app, SLOT(quit()));

   return app.exec();
}

【讨论】:

【解决方案2】:

您可以将任意数量的信号连接到任意数量的插槽(以及其他信号)。为此,将信号连接到两个插槽是非常有意义的。插槽按照它们连接的顺序被调用。连续发射两个信号也是完全合理的。当然 readyToBeDeleted() 应该在 succeeded() 之后发出,这样对象在发出结果信号之前就不会被删除。

除非我误解了你,否则就这么简单。

【讨论】:

  • 从我读到的,插槽被调用的顺序是随机的。我只是想以某种方式解决这个问题,这样我就不必将每个信号连接两次
  • @chikuba 不,根据docs,“如果多个槽连接到一个信号,则槽将按照连接的顺序一个接一个地执行,当信号被发射。”
  • 但我不会将多个插槽连接到一个信号。我通过某种方式将来自一个对象的每个信号实际连接到一个特定的插槽
  • @chikuba 您不能自动将来自对象的每个信号连接到给定插槽。您必须按照您希望他们被解雇的顺序一个接一个地手动完成。我不明白这是什么问题。
  • 文档声明doc.trolltech.com/4.5/signalsandslots.html#signals“如果多个槽连接到一个信号,则在发出信号时,这些槽将按任意顺序依次执行。”他们一定是刚刚改变了这个:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
  • 1970-01-01
  • 1970-01-01
  • 2016-03-20
  • 2016-10-03
  • 1970-01-01
相关资源
最近更新 更多