【问题标题】:QML Why Window.requestUpdate() is not working?QML 为什么 Window.requestUpdate() 不起作用?
【发布时间】:2019-11-04 11:26:22
【问题描述】:

我有一个 Qt 快速窗口:

Window{
   id: mainWindow
   ...
}

我想在 QML 中的长阻塞操作之前显示一个消息框:

// Set visible=true of 'messageBox' Rectangle{}
messageBox.showWaitMessage("Please wait")

// I want to show it before blocked the screen
mainWindow.requestUpdate()

// Long blocking operation:
compressFile("filepath")

屏幕中的所有对象都是mainWindow的子对象。


但它不起作用。在阻塞操作之前它仍然不重绘屏幕。

为什么?

【问题讨论】:

  • 可能你的compressFile 阻塞了GUI线程。您应该在单独的线程中运行长时间操作。
  • 我知道它会阻塞。这就是为什么我想在屏幕阻塞之前刷新屏幕:)
  • 不,您请求更新,而不是真正更新 GUI。
  • 是的,这就是为什么它不起作用+1,我认为它是(requestUpdate)强制屏幕立即更新。
  • 反正GUI编程要求主线程不会被用户阻塞。此外,您还有在单独的线程中运行任务的工具——QML 中的 WorkerScript 或 C++ 中的 QThread。

标签: qt qml window redraw


【解决方案1】:

这是因为调用这些调用的函数尚未完成,而排队等待由事件循环执行的 requestUpdate() 实际上将在 compressFile 之后发生。 这是设计不良的标志,最好将您的 compressFile 移动到另一个线程。如果线程不是一个选项,您可能希望像这样间接调用compressFile,这会将调用放入队列中。然后 GUI 事件循环将在执行计时器槽之前重新绘制小部件。您无需手动更新 GUI。

QTimer::singleShot(0, [=]() { compressFile("filepath") } );

这仅适用于 Qt5.4 及更高版本,因为 QTBUG-26406。 如果您使用的是较低版本的 Qt,您可以执行相同的操作,例如:

    QTimer *timer = new QTimer(this);
    timer->setSingleShot(true);
    connect(timer, &QTimer::timeout, [=]() {
       compressFile("filepath");
       timer->deleteLater();
    } );
    timer->start(0);

【讨论】:

  • 这不是我一直在寻找的,但它提供了另一种解决方法:+1:。实际上我认为 mainWindow.requestUpdate() 类似于 C++ 端的 repaint() 。所以还是谢谢:)
猜你喜欢
  • 2017-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 2019-12-03
  • 1970-01-01
相关资源
最近更新 更多