【问题标题】:GUI update and control at the same time in qtqt中GUI更新和控制同时进行
【发布时间】:2017-12-16 06:38:31
【问题描述】:

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

【问题讨论】:

  • 你能分享你的代码吗?您是否在代码中使用了 Sleep 命令?
  • 你能分享你的代码吗?在大多数情况下,计时器是正确的方法。如果单击未执行,则可能是您的代码中存在问题,可能是某些阻塞功能,您可能可以使用信号/插槽或线程重新排列。
  • 感谢您的回复。那么你是说即使我在触发计时器时单击按钮也不会引起任何问题?明天我会尝试发布代码..再次感谢
  • 我的代码中没有使用 sleep 命令。

标签: c++ multithreading qt user-interface


【解决方案1】:

有三种主要方法可以做到这一点,每种方法都有其优点和缺点。

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


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

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

优点

  1. 非常简单
  2. 没有并发问题

缺点

  1. 功能非常有限
  2. 污染代码

线程

如果您想要一个简单但可扩展的解决方案,子类化 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. 稳健、可扩展且信号/插槽允许数据交换

缺点

  1. 不能从主线程以外的任何线程更新 GUI。
  2. 信号/槽必须使用 QueuedConnection。

事件循环

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

QTimer timer;
QEventLoop loop;

timer.setSingleShot(true);
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));

timer.start(5000); 
loop.exec();

这在很大程度上不太直观,但在大多数情况下通过避免忙等待会好得多。


优点

  1. 最少的 CPU 使用率

缺点

  1. 不太直观。

您可以阅读更多here。我最初有一个包含相同信息的现代资源,所以如果你在 Qt5 文档上找到类似的链接,请编辑这篇文章。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-12
      • 2021-09-29
      • 1970-01-01
      相关资源
      最近更新 更多