在qt中同时更新和控制GUI

时间:2017-07-12 02:39:36

标签: c++ multithreading qt user-interface

我正在尝试创建一个用于在QT中控制和监控工业机器的GUI。 GUI应该使用机器的测量值每300ms更新一次。我应该能够同时控制机器。我正在做什么(错误)是我试图使用定时器更新GUI中的测量值,该定时器每300ms触发一次。但是如果我在执行定时器插槽的同时单击我的控制按钮,则GUI没有响应。我也试过使用信号和插槽技术。结果相同。我无法在互联网上找到解决方案。如果有人可以提供帮助,我会很高兴。提前谢谢。

2 个答案:

答案 0 :(得分:1)

这样做有三种主要方法,每种方法都有其优点和缺点。

简单,不可扩展的解决方案

最简单的方法是在您的"忙碌"内拨打QApplication::processEvents()代码手动。例如,要手动更新每个循环的GUI,您可以这样做:

for (int i = 0; i < 5000; ++i) {
    label->setText(tr("At Index %1...").arg(i));
    QApplication::processEvents();
}

<强> 赞成

  1. 很简单
  2. 无并发问题
  3. <强> 缺点

    1. 功能非常有限
    2. 污染代码
    3. <强>线程

      如果你想要一个简单的解决方案,但是可扩展的解决方案,继承QThread,然后在一个单独的线程中运行非GUI任务是一个很好的方法:

      class MyThread: QThread
      {
          Q_OBJECT
      
          void run()
          {
              for (size_t i = 0; i < 50000; ++i) {
                  std::cout << i << std::endl;
              }
          }
      };
      
      auto *thread = new MyThread;
      thread->start();
      

      当长任务发生时,GUI将更新,Qt将负责垃圾收集。

      <强> 赞成

      1. 相当简单
      2. 强大,可扩展,信号/插槽允许数据交换
      3. <强> 缺点

        1. 无法从主线程以外的任何线程更新GUI。
        2. 信号/插槽必须使用QueuedConnection。
        3. 事件循环

          最后一种方法是Qt的原生解决方案:QEventLoop。

          QTimer timer;
          QEventLoop loop;
          
          timer.setSingleShot(true);
          connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
          
          timer.start(5000); 
          loop.exec();
          

          这实际上不那么直观,但在大多数情况下,通过避免忙碌等待,情况会好得多。

          <强> 赞成

          1. 最低CPU使用率
          2. <强> 缺点

            1. 不太直观。
            2. 您可以阅读更多here。我最初拥有一个具有相同信息的现代资源,因此如果您在Qt5文档中找到类似的链接,请编辑此帖子。

答案 1 :(得分:0)

我发现了问题所在。这不是我想象的那样。我要求每隔30毫秒与我通信的机器的状态。我把它增加到了3000毫秒,现在它工作正常。即使在执行另一个插槽时单击该按钮,该按钮也不会引起任何问题。这是一个愚蠢的问题。感谢大家的帮助。所有答案都非常有用。再次感谢。