【问题标题】:QT: Run a function as long as button is toggledQT:只要按钮被切换就运行一个功能
【发布时间】:2021-04-27 10:25:57
【问题描述】:

我想实现一个从外部设备接收消息的 GUI。 “advancedReceiveExample”正在等待消息。一旦它收到一个,它就会处理它,保存它并终止。

只要按钮被切换,我想让我的函数在收到新消息后等待新消息。

到目前为止我已经尝试过了:

void MainWindow::on_pushButton_clicked()
{
    if (ui.pushButton->isChecked()) {
        ui.pushButton->setText("Stop Receiving");
        ui.label_3->setText("Receiving...");

        advancedReceiveExample(ui.comboBox->currentIndex() + 1);
    }
    else
    {
        ui.pushButton->setText("Start Receiving");
        ui.label_3->setText("Not Receiving");
    }
}

这工作得很好,但如上所述,它只收到一条消息。如果我这样做:

void MainWindow::on_pushButton_clicked()
{
    if (ui.pushButton->isChecked()) {
        ui.pushButton->setText("Stop Receiving");
        ui.label_3->setText("Receiving...");

        while (1)
        {
            advancedReceiveExample(ui.comboBox->currentIndex() + 1);
        }
    }
    else
    {
        ui.pushButton->setText("Start Receiving");
        ui.label_3->setText("Not Receiving");
    }
}

它阻塞了该函数,因为只有在函数“on_pushButton_clicked()”终止后才能更改按钮的状态。


Visual Studio 2019 C/C++


编辑:好的,我已经理解了阻塞线程的问题。多线程可能是正确的选择,但我对这个主题非常缺乏经验。 <QThread> 是可能的。你会怎么用呢?

您有什么建议可以使用其他库吗?

【问题讨论】:

  • 如果您不想阻塞 UI 线程,那么您需要在单独的线程上运行消息泵。
  • 我假设您想使用pressedreleased 信号,而不是clicked

标签: c++ multithreading qt user-interface toggle


【解决方案1】:

注意 QT 是基于事件的。如果您让您的计算机忙于某些功能而不经常返回主外观,您的 GUI 将冻结。

您需要做的是将您想要执行的操作切成小块,这些小块可以重复返回到主循环,以保持 GUI 响应。 (另一种方法是将您的操作换成单独的线程并并行处理,在释放按钮时终止线程)

可能最简单的方法是使用您在 PushButton::clicked 插槽中设置的计时器,然后在计时器事件中检查按钮是否仍被按下,如果是,请执行一些您的操作操作、保存状态并重新启动计时器以让您返回。

类似于以下伪代码行的东西应该可以工作并每 10 毫秒执行一次您想要在切片中执行的操作:

MainWindow::onPushButtonClicked () {
   // do the  action, or, alternatively, start a 
   // parallel thread that does it
   do_a_bit_of_action();
   // sets up a timer to call onTimer after 10ms
   QTimer::singleShot (10, this, SLOT(onTimer()));
}


MainWindow::onTimer () {
   // check if button is still held down
   if (pushButton.down) {
      // re-arm timer
      Timer::singleShot (10, this, SLOT(onTimer()));
      // do some more action bits
      do_a_bit_of_action();
   }
   else {
      // kill optional background thread here
   }
   
}

【讨论】:

  • 感谢您的回答!我认为多线程可能会更好,因为等待消息会阻塞线程。昨天之前我还没有意识到这一点。
  • 嗯,取决于你的问题。如果“后台任务”只是简单的一点图形动画,例如“定时器”方法就可以了。如果您的 BGT 需要在严格的时间限制内完成重要的工作,那么增加线程的复杂性可能是合理的。请注意,线程可能会添加许多其他与并发相关的并发症。
【解决方案2】:

你可以试试:

while(ui.pushButton->isChecked()){
   *your function*
}

【讨论】:

  • 感谢您的回答,但只要“isChecked”为真,我将保留在“on_.._clicked”功能中,因此我无法取消选中按钮,所以这仍然是一个永无止境的斜坡。
  • 否,因为在每个循环中都会检查 ui.pushButton->isChecked()
猜你喜欢
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 2018-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多