Qt:有什么方法可以调用具有特定时间间隔的一系列插槽?

Qt: is there any way to call a sequence of slots with certain time interval?

我现在的工作方式是将 QTimer 连接到第一个插槽,在第一个插槽内它将触发另一个单发 QTimer ,这将触发第二个插槽...等等。

如果我一次更新所有小部件,GUI 会卡住一秒钟。但这是显而易见的。所以我想避免这种情况。

但是这个代码很难写。您必须在所有地方添加 QTimer。有没有更好的解决方案?

编辑:这就是我更新小部件的方式,也许有更好的方法?

void UAVInfoView::updateDisplay()
{

    if (!visibleRegion().isEmpty()){
        info = _dataSrc->getUAVInfo(_id-1);
        if (info)
        {
            //if new package received try to do updating.
            if (_pakchk != info->_pakcnt){
                //only update the text if there is communication
                if (info->_communication != COMMSTATUS::WAIT4CONNECTION && info->_communication != COMMSTATUS::LOST)
                {
                    ui->plainTextEdit->setPlainText(tr("x: %1\ny: %2\nz: %3").arg(info->_pos[0]).arg(info->_pos[1]).arg(info->_pos[2]));
                }
                //only update the status indicator only if status changed.
                if (_status != info->_communication)
                {
                    switch (info->_communication){
                    case COMMSTATUS::CONNECTED:
                        ui->groupBox->setStyleSheet("QGroupBox#groupBox {background-color:green;}");
                        ui->label_2->setText("On Line");
                        break;
                    case COMMSTATUS::LOST:
                        ui->groupBox->setStyleSheet("QGroupBox#groupBox {background-color:red;}");
                        ui->label_2->setText("Lost");
                        break;
                    case COMMSTATUS::WAIT4CONNECTION:
                        ui->groupBox->setStyleSheet("QGroupBox#groupBox {background-color:grey;}");
                        ui->label_2->setText("Off Line");
                    }
                }
            }
            //update the status and package counter to serve the state machine.
            _status = info->_communication;
            _pakchk = info->_pakcnt;
        }
    }
}

如你所见,它只是一堆默认的 =, !如果还有其他事情...

我不太清楚你想达到什么目的,但是如果你想用定时器触发一组特定的函数的执行,你可能需要引入一些带有单个的控制实例 QTimer,您可以随意使用。

既然你说你不想一直更新所有的 GUI 小部件,我猜你正在使用 QWidgets,你也可以使用 setUpdatesEnabled(bool) 方法来禁用所有update()repaint() 调用的效果。

如果这对您没有帮助,也许您可​​以更详细地解释您的问题?

如果更新方法比较复杂,您应该尝试QtConcurrent::map()到运行在另一个线程中更新。然后你不需要延迟,因为当更新完成时你会收到 map() 的通知。

虽然我认为问题出在其他地方,但我会给您一个可能的解决方案。你可以使用状态机。只有一个由计时器触发的插槽,您可以在其中根据当前状态调用一些其他函数。

...
connect(&timer, SIGNAL(timeout()), this, SLOT(myStateSlot()));
timer.start(1000);
...


void MyClass::myStateSlot()
{
    switch(state)
    {
    case State_Start:
        operation1();
        // you can change the state here.. or somewhere else.. up to your design
        break;
    case State_Two:
        operation2();
        break;
    case State_End:
        timer.stop();
        break;
    }
}

您可以在连接到计时器的插槽中以一定间隔调用它们。您连接到计时器的插槽可能像:

void myClass::onTriggered()
{
    switch(turn){
       case 0:   
           slot1();
           break;
       case 1:
           slot2();
           break;
       ...
    }

    turn++;
    if(turn>=numberOfSlots)
        turn = 0;
}

这样每次调用一个slot,然后依次调用。

您的问题可能源于 QPlainTextEdit 的相对缓慢。请改用 QLabel。否则,代码看起来不错。确保如果有多个对 updateDisplay 的后续调用,它们都应该在没有控制 return 调用之间的事件循环的情况下发生。

以下是错误的,因为每个 processEvents 都会强制重新绘制小部件。

w.updateDisplay();
QCoreApplication::processEvents();
w.updateDisplay();
QCoreApplication::processEvents();

您可能在没有意识到的情况下调用了 processEvents()。每当您从 QObject::event() return 事件队列当时为空时,它都会被有效地调用。另请注意,QObject::event() 是排队插槽调用的调用方。因此,如果您有一个到插槽的排队连接,控件 returns 将在插槽 returns 之后立即进入事件循环。