避免 QQuickView 延迟 qml 加载

Posted

技术标签:

【中文标题】避免 QQuickView 延迟 qml 加载【英文标题】:Avoid QQuickView delayed qml loading 【发布时间】:2016-09-05 09:35:36 【问题描述】:

这是我的情况。我正在尝试将 qml 与主要基于小部件的 UI 结合起来。为此,我将 QQuickView 与 QWidget::createWindowContainer 一起使用。我不能使用 QQuickWidget,因为我需要将窗口转换为原生窗口,而 QQuickWidget 不喜欢这样。但回到问题上来。

我的问题是第一次显示视图时,加载大约需要半秒钟,导致非常明显的闪烁。之后我可以隐藏/显示我想要的所有视图,它会立即显示。这只是第一次加载 qml。而且我相当确定这是导致问题的 qml 的加载。因为我有两个不同的 QQuickViews,它们的源代码相同。但是其中任何一个加载一次后,另一个立即显示没有问题。

我尝试尽早调用 show() on view 以使其及时加载。但这会导致 qml 在显示任何小部件之前出现片刻。

有没有人遇到过类似的问题?如何让 QQuickView 正常运行。

编辑:我使用的是Qt 5.4.2,由于各种原因我无法更新到较新的版本。

【问题讨论】:

【参考方案1】:

我想说您可以使用与this 答案中相同的方法,但似乎即使这样加载 QML 还为时过早。这很 hacky,但我唯一能想到的另一件事是使用非常短的 Timer

ma​​in.cpp

#include <QtWidgets>
#include <QtQuick>

class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0) :
        QMainWindow(parent)
    
        QQuickView *view = new QQuickView();
        QWidget *container = QWidget::createWindowContainer(view, this);
        container->setFocusPolicy(Qt::TabFocus);
        view->rootContext()->setContextProperty("window", view);
        view->setSource(QUrl("qrc:/main.qml"));
        setCentralWidget(container);
        resize(400, 400);
    
;

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();


#include "main.moc"

ma​​in.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.0

Item 
    anchors.fill: parent

//    Connections 
//        target: window
//        onAfterSynchronizing: loader.active = true
//    

    Timer 
        running: true
        repeat: true
        interval: 50
        onTriggered: 
            loader.active = true
        
    

    Loader 
        id: loader
        active: false
        sourceComponent: Column 
            anchors.fill: parent

            Repeater 
                model: 30000
                delegate: Button 
                    text: index
                
            
        
    

    BusyIndicator 
        running: loader.status === Loader.Null
        anchors.centerIn: parent
    

为简洁起见,我将“重”QML 放入 sourceComponent,但您也可以使用 source 属性指向 URL。

BusyIndicator 在渲染线程上运行其动画,因此它可以在 GUI 线程被阻塞时继续旋转。

【讨论】:

我查看了您的解决方案,但随后注意到您使用了我无法访问的 qml 组件。我道歉,我应该在问题中提到它。但希望这对其他有类似问题的人有用。 您可以将import QtQuick.Controls 2.0 更改为import QtQuick.Controls 1.3(或随Qt 5.4.2 发布的任何版本的控件),它应该可以正常工作。 对不起,我的错。我一定是查错了什么。我设法尝试了您的解决方案,但遗憾的是它无法解决我的问题。如果您有一个需要时间加载的复杂 qml,这很有用。我的问题是,即使是一个非常简单的单键 qml 第一次加载也需要一秒钟的时间。使用您的解决方案,加载程序本身需要一秒钟才能出现,在我的 qml 出现之前,我几乎无法辨认出加载圈。

以上是关于避免 QQuickView 延迟 qml 加载的主要内容,如果未能解决你的问题,请参考以下文章

带有 QQuickView 的 QML 信号 QT 插槽

将 QML(QQuickView) 添加到现有 UI

使用 QQuickView 或 QQuickWidget 在 QWidget 应用程序中添加大量 QML 对象会带来性能问题

如何更改 QQuickView 的来源

在 Qt5.3(mingw32) 中删除 QQuickView 的内存管理问题

QQuickView 新删除类型不匹配