QQuickView - 无延迟/滞后地调整内容大小

4

图片通常是解释问题最简单的方法,这是我遇到的问题的截图:

laggy resize

如果你看一下窗口的右侧,你会发现内容被调整大小时有一定的可见延迟。这在很多应用程序中都会出现,但我想知道是否有一种方法可以在使用QQuickView和QML内容的Qt应用程序中解决此问题。

基本上我的应用程序是这样创建的:

QQuickView view;
view.resize(400, 200);
view.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
view.setSource(...);

QML的内容只是一个带有两个矩形框来突出显示问题的项目。
编辑:这是QML文件的简化版本(是的,简化版本也存在相同的问题 ;p)。
import QtQuick 2.12
Item {
    Rectangle {
        color: "black"
        anchors { fill: parent; margins: 10 }
    }
}

编辑2:将此小QML片段通过qmlscene可执行文件运行,也会显示相同的延迟/滞后。

编辑3:在某些Linux发行版上会出现相同的问题,但在其他一些发行版上则不会:在我的Ubuntu上它可以正常工作,但在我的CentOS 7上,就像Windows上一样出现了相同的延迟/故障。两个Qt版本均为5.12.3。在旧版的OSX上它可以正常工作(在Qt 5.9上测试)。我真的很迷茫^^

有没有办法防止这种延迟?解决方案可能是特定于平台的,因为似乎问题来自于本机帧在Qt有可能获得事件之前被调整大小,因此内容会延迟1帧重新调整大小...但我想知道是否有人有关于如何处理这个问题的想法?

欢迎任何帮助或指针 :)

问候, 达米安


在我的Linux环境中,使用您提供的QML和Qt 5.12.3版本,我没有观察到您所指出的问题。请问您能否提供您在图像中使用的QML文件? - eyllanesc
1
那么,这要么是平台特定的错误(例如,在Linux上工作,在Windows上不工作),要么是C++部分存在差异:正如我在帖子中所写的,我编写的简化QML示例也表现出与屏幕截图中相同的延迟 - Citron
如果问题与特定操作系统有关,那么很可能是一个错误,而且在SO上寻找解决方案并不是正确的做法,建议将错误报告给Qt。 - eyllanesc
这是QML属性绑定异步性的一部分。这让我想起了一个问题,当我移动一个无边框的“Window”时,我必须通过调用“cursorPos()”从C++中获取坐标,否则窗口会跳来跳去。您可以遵循相同的逻辑,从C++中获取“window”尺寸,并直接将其设置为您的“Item”。如果您成功实现,请在此处发布。祝好运! - bardao
属性绑定和QML在我所知道的范围内完全独立于平台:如果这是问题,它应该发生在所有平台上而不仅仅是Windows上。 我尝试着重写QQuickView的nativeEvent,并注意到一些奇怪的事情:当从左侧调整大小时,我们按此顺序接收移动和大小本机事件。但然后QQuickView的相应moveEvent和resizeEvent方法以相反的方式被调用(先调用resize再调用move)。但这对我的理解来说有点太低级了,所以我停止了调查。 - Citron
显示剩余4条评论
2个回答

0
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);

使用OpenGL后没有明显的延迟。

如果有延迟的话,请尝试以下代码:

if (msg == WM_NCCALCSIZE) {
   *result = WVR_REDRAW;
   return true;
}

0

正如您在更新中提到的那样 - 内容会延迟1帧进行调整大小。 而且有一个非常简单的方法来处理这个问题。 使用nativeEventFilter,处理WM_NCCALCSIZE并将pMsg->wParam == TRUE从顶部或底部减去1像素。

if( pMsg->message == WM_NCCALCSIZE and pMsg->wParam == TRUE )
{
    LPNCCALCSIZE_PARAMS szr = NULL;
    szr = reinterpret_cast<LPNCCALCSIZE_PARAMS>( pMsg->lParam );
    if( szr->rgrc[0].top != 0 )
    {
        szr->rgrc[0].top -= 1;
    }
}

问候,安东。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接