2

我现在的工作方式是将 a 连接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;
        }
    }
}

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

4

5 回答 5

2

我不太确定你试图实现什么,但如果你想用计时器触发一组特定函数的执行,你可能必须引入一些控制实例QTimer,你可以随意使用它.

既然您说您不想一直更新所有 GUI 小部件,而且我猜您正在使用QWidgets,您还可以使用该setUpdatesEnabled(bool)方法禁用update()orrepaint()调用的所有效果。

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

于 2015-02-27T13:55:57.163 回答
2

您可以在连接到具有特定间隔的计时器的插槽中调用它们。您连接到计时器的插槽可能类似于:

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

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

这样,每次调用一个插槽时,它们都会被顺序调用。

于 2015-02-27T14:04:27.803 回答
1

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

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

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

您可能会在processEvents()没有意识到的情况下调用它。每次返回时都会有效地调用它,QObject::event() 并且当时事件队列为空。另请注意,这QObject::event()是排队插槽调用的调用者。因此,如果您有与插槽的排队连接,则控件会在插槽返回后立即返回事件循环。

于 2015-02-27T16:58:39.780 回答
1

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

...
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;
    }
}
于 2015-02-27T14:03:32.177 回答
0

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

于 2015-02-27T14:01:23.390 回答