【问题标题】:Force Qt custom signal to be processed immediately?强制 Qt 自定义信号立即处理?
【发布时间】:2016-02-29 08:46:34
【问题描述】:

我对 Qt 及其信号/插槽机制有疑问。
我创建了一个自定义小部件,并创建了一个自定义SIGNAL (ShowMessage)。此信号连接到SLOT,它在我的主窗口的状态栏中显示消息(以及指定的超时)。

现在,我的班级中有一个操作需要很长时间才能执行,并且它阻塞了 UI。我希望在开始操作之前emit我的信号,当它完成后,emit再次更新状态栏;像这样:

emit ShowMessage(message, timeout);
// Do the long operation
emit ShowMessage(newMessage, timeout);

但我的问题是Qt似乎一直等到整个操作完成,并且只用newMessage更新状态栏。
有没有办法以某种方式“强制”立即处理我的信号,因为如果我想求助于线程,那么我的生活会变得更加复杂!

【问题讨论】:

  • 这是什么长操作?为什么很难将其移至新线程?
  • 您是否使用 Qt::DirectConnection 进行连接? - 这应该确保您的信号已经被立即处理。如果不是,那么您应该使用调试器单步执行并查看发生了什么。我假设这一切都发生在同一个 GUI 线程中?
  • 抱歉,我不明白您所说的Qt::DirectionConnection 是什么意思。我是 Qt 新手,我将它用作我的 OpenGL 绘图的容器。
  • @thuga 长操作实际上是 OpenGL 调用加载模型(并缓冲其数据);我不确定如何在单独的线程中完成

标签: c++ qt signals-slots


【解决方案1】:

有没有办法以某种方式“强制”立即处理我的信号

是的,有。 :-)。 显示第一条消息后,请致电QCoreApplication::processEvents()。这会强制在调用点处理所有未决事件。例如,

emit ShowMessage(message, timeout);
QCoreApplication::processEvents();
// Do the long operation
emit ShowMessage(newMessage, timeout);

【讨论】:

  • 非常感谢您的回答 :) 它解决了最初的问题,但它在我的应用程序中产生了另一个问题。我不知道您对 OpenGL 的熟悉程度,但我在我的应用程序中调用本机 API OpengGL 方法,现在在调用 glDrawElements 时收到“访问冲突错误”。你知道这里发生了什么吗?我不知道添加这个方法和我的 OpenGL 调用之间有什么联系
  • @Farzad 您正在同步编码。不要,你的问题就会消失。从事件循环调用的所有内容(因此,连接到 Qt 信号的所有插槽)都需要快速运行以完成。您的信号 立即处理,但由于您阻塞了事件循环,小部件永远没有机会重新绘制自己。您不能阻止事件循环。如果您需要在 GUI 线程中进行长时间处理,请分小块进行,作为对零持续时间计时器到期的反应。不要递归到processEvents,它可以重新输入您的代码,我认为这是不好的建议。
  • @KubaOber 你能详细说明一下你提到的计时器吗?我是 Qt 的新手,我将它用作调用 OpenGL 函数的容器。我的“长”操作实际上是从文件中加载(和缓冲)模型,所以我不知道您使用计时器是什么意思
  • @Farzad 将您的长操作分解为许多短操作。要开始操作,您可以connect(new QTimer(this), &QTimer::timeout, this, &MyClass::myOperation)myOperation 应该在每次被调用时做大量工作,然后返回。完成工作后,它应该通过执行delete sender() 取消计时器。这将是作为概念证明的最小方法,您当然不需要为此动态分配的计时器。
  • 那么,有没有办法做这样的事情:创建一个计时器并开始操作,并从计时器知道操作已完成?我的意思是,一种以某种方式等待操作完成并继续我们之前所做的事情的方法
猜你喜欢
  • 1970-01-01
  • 2018-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多