QMLwindowresize/move闪烁

QML window resize/move flicker

我现在正在开发一个简单的 QML 应用程序,我注意到调整大小和移动 QML window 与 QtWidgets window,例如。

所以我创建了 2 个测试应用程序来显示差异:

QWidgets:

QML:

如您所见,QML 版本的应用程序闪烁得非常难看,而 QtWidgets 版本是干净的。现在,当您的 UI 变得越来越复杂时,这会变得非常丑陋。

你有这方面的知识吗?这是一个错误吗?这个问题有没有fix/workaround?

你可以试试这个:

int main(int argc, char* argv[]) {
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
or
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);

第一个选项使用 OpenGl2DirecX 角度库(如 Google Chrome)

第二个通过软件使用 OpenGL 仿真...对于小程序来说效果很好,并且 100% 兼容旧的 OS,例如 Windows XP。

注意:您可以尝试使用 Qt 5.7 和新的 Qtquick.Controls 2.0 ...性能更好... https://blog.qt.io/blog/2016/06/10/qt-quick-controls-2-0-a-new-beginning/

就我而言,我通过添加下一个标志解决了这个问题:

QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);

但这会增加其他渲染问题。还是不行。

调整 QML 应用程序大小的问题是关于用 过时的 几何更新 window。解决方法是同步更新和调整大小。

由于更新计时器可能会突然更新渲染场景图,可以随时更新window,因此会导致绘制的内容具有过时的几何图形。 https://bugreports.qt.io/browse/QTBUG-46074

应使用基本同步或扩展同步来同步调整大小和 window 更新。 当前基本同步在 Qt 中使用和实现,但仍需要将 window 更新(来自计时器)与来自 Windows 管理器的调整大小事件同步。

但是,一如既往,有一个问题列表:

当 window 调整大小过快时会出现问题。 由于同步事件(来自 WM)应该一致发送,下一个在上一个之后:

  1. <= _NET_WM_SYNC_REQUEST 是从WM发来的,现在大小有变化。

  2. _NET_WM_SYNC_REQUEST 由应用程序接收和处理。

  3. <= 收到了一些其他事件,例如新几何体。

  4. ..更新内容,swapBuffers.

  5. => 已将 _NET_WM_SYNC_REQUEST_COUNTER 发送回 WM。

  6. <= _NET_WM_SYNC_REQUEST 再次从WM发送,大小正在改变。

  7. .. swapBuffers // 这就是问题所在,更新是在 window 改变其几何形状时执行的。

  8. _NET_WM_SYNC_REQUEST 收到再处理

因此,当 (7) swapBuffers 在 _NET_WM_SYNC_REQUEST 发送后出现但尚未 received/processed 时出现问题。

最后得出结论:

  • window 的实际大小调整是在 _NET_WM_SYNC_REQUEST 由 Window 经理发送后立即开始的。 而不是当应用程序收到它。 window 甚至可以在此时更新,当发送同步请求但应用程序尚未处理时。这将使用过时的几何图形绘制内容。
  • _NET_WM_FRAME_DRAWN 可以帮助在调整大小和更新之间进行同步,但 Window 管理器也可能不支持(并且猜测不支持)。

换句话说,基本同步或扩展同步都无济于事(至少没有 _NET_WM_FRAME_DRAWN),因为无法知道实际调整大小何时完成。

扩展同步协议试图解决这个问题,但是由于几何的实际更改是在没有与客户端同步的情况下完成的,正如我所见,没有 _NET_WM_FRAME_DRAWN 总是有机会更新 window 具有过时的几何形状。

https://lists.freedesktop.org/archives/xcb/2019-February/011280.html

在 golang 中 therecipe/qt 这对我有帮助:

func main() {
    var format = gui.NewQSurfaceFormat()
    format.SetVersion(4, 5)
    format.SetProfile(gui.QSurfaceFormat__CoreProfile)
    format.SetRenderableType(gui.QSurfaceFormat__OpenGL)
    format.SetSwapInterval(0)
    format.SetDefaultFormat(format)
    os.Setenv("QT_SCALE_FACTOR", "1")
    ap := widgets.NewQApplication(len(os.Args), os.Args)
    ap.SetApplicationName("APP 1.1")

系统:Linuxdebian 10 显卡:Radeon 570

但动画速度更快,因为并非所有帧都被渲染...