你能改变Qt连接的队列大小吗?

时间:2014-01-22 15:15:47

标签: c++ qt signals-slots

在Qt中,您可以通过将一个对象中的信号设置为另一个对象中的一个插槽然后使用“connect()”连接它们来连接两个对象。

现在,通过在一个对象中发出信号,它将被发送到第二个对象。我有一个接受用户输入的系统,如果用户输入太多,我希望我的“队列”填满,不再接受任何输入。

我可以在接收对象上实现一个回复机制,但是我想知道我们是否可以建立一个队列大小(例如)1。因此只会处理一条消息,并且任何新的发射都会被简单地移除,直到“管道”有空间。

这可能在Qt吗?

在我的情况下,这两个对象在不同的​​线程中并且具有排队连接(如果这有任何区别)......

MainWindow::MainWindow()
{
    // Make object 1, stick it in another thread
    MyObjType1 *obj1 = new MyObjType1();
    anotherThread = new QThread; // anotherThread  is type QThread *
    obj1->moveToThread(anotherThread);
    anotherThread->start();

    // Make object 2, connect a signal to obj1
    MyObjType2 *obj2 = new MyObjType2();
    connect(obj2, SIGNAL(obj2Signal(int), obj1, SLOT(obj1Slot(int), Qt::QueuedConnection);

    // Hammer obj1 with signals to its queue
    for (int i = 0; i < 100000; i++)
    {
        emit obj2->obj2Signal(i);
    }
}

因此,想法是obj1获取大量信号,它处理第一个信号,并以某种方式抛弃其他信号直到它完成,然后接受下一个发射的信号。

1 个答案:

答案 0 :(得分:1)

对于排队连接,对于连接到信号的每个插槽,都会在连接的插槽对象的事件队列中发布QMetaCallEvent。事件循环运行时会传递事件。以下代码输出:

about to emit
done emitting
in aSlot() 
class MyObject {
  Q_OBJECT
  Q_SIGNAL void aSignal();
  Q_SLOT void aSlot() { qDebug() << "in aSlot()"; }
public:
  MyObject(Qt::ConnectionType conn = Qt::AutoConnection) {
    // QObject::connect() defaults the connection type to Qt::AutoConnection,
    // we merely duplicate this behavior.
    connect(this, SIGNAL(aSignal()), SLOT(aSlot()), conn);
    qDebug() << "about to emit";
    emit aSignal();
    qDebug() << "done emitting";
  }
};
int main(int argc, char ** argv) {
  QCoreApplication app(argc, argv);
  MyObject obj(Qt::QueuedConnection);
  QCoreApplication::processEvents();
  return 0;
}

现在可以将问题重新表述为:如何强制从事件队列中删除重复的QMetaCallEvent事件?这称为事件压缩。我有already provided a canonical answer to that question。对于用户输入,您希望保留最近发出的信号,而不是最旧的信号,但我已在答案代码中实现了这两种行为。

使用我的答案中的代码,您的示例仅需要main()函数中的以下内容:

int main(int argc, char ** argv) {
    CompressorApplication<QApplication> app(argc, argv);
    app.addCompressedSignal(MyObjType2::staticMetaObject.method(MyObjType2::staticMetaObject.indexOfSignal("obj2Signal(int)")));
    MainWindow w;
    w.show();
    return app.exec();
}

注意:如果正在连接具有默认Qt::AutoConnection 的对象,则对象位于同一个线程中,那么队列的概念根本不适用。在信号函数返回之前调用插槽,不需要排队!下面的代码将输出:

about to emit
in aSlot()
done emitting
// MyObject as above
int main(int argc, char ** argv) {
  QCoreApplication app(argc, argv);
  MyObject obj;
  return 0;
}