QML优化,当列表数据过多时,切换tab可能会导致卡顿的情况。

QML优化,当列表数据过多时,切换tab可能会导致卡顿的情况。_qml 做的页面,页面切换速度会慢吗-CSDN博客

当列表数据过多时,切换tab可能会导致卡顿的情况。为了优化这个问题,我们可以采取以下措施:

    分页加载数据:不要一次性加载所有数据,而是分页加载。当用户切换到列表时,只加载当前页的数据,而不是全部数据。这可以减少初始加载时间和内存占用。

    使用虚拟视图:在QML中,可以使用ListView的flickableItem属性来实现虚拟视图。这意味着只有在视图中可见的项才会被实例化,而不是所有项都会被创建。这可以减少内存占用和加速切换tab的速度。

    异步加载数据:使用后台线程来加载数据,以避免阻塞主线程。这样可以确保用户界面在加载数据时仍然保持响应。

    数据缓存:对于已加载的数据,可以进行缓存,以便在用户切换回来时不需要重新加载数据。

    优化数据模型:如果可能的话,可以对数据模型进行优化,例如使用QAbstractListModel来实现自定义数据模型,以提高数据的访问效率。

下面是一个简单的示例,演示了如何使用分页加载、虚拟视图和异步加载来优化列表数据过多时切换tab的性能问题。

1.QML部分:

main.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
import com.example 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Tab View Example")

    TabView {
        anchors.fill: parent

        Tab {
            title: "Tab 1"
            ListView {
                id: listView1
                anchors.fill: parent
                model: {
                    var model = Qt.createQmlObject("import QtQuick 2.12; ListModel {}", parent);
                    for(var i = 0; i < 100; i++){
                        model.append({"text": "Item " + i});
                    }
                    model
                }
                delegate: Item {
                    width: parent.width
                    height: 40
                    visible: index >= listView1.currentIndex - 5 && index <= listView1.currentIndex + 5
                    Text {
                        text: modelData.text
                        anchors.fill: parent
                        horizontalAlignment: Text.AlignHCenter
                        verticalAlignment: Text.AlignVCenter
                    }
                }
            }
            Component.onCompleted: {
                var generator = new RandomDataGenerator();
                generator.dataGenerated.connect(function(data){
                    RandomDataGenerator.onDataGenerated(data, 1);
                });
                generator.start();
            }
        }

        Tab {
            title: "Tab 2"
            ListView {
                id: listView2
                anchors.fill: parent
                model: {
                    var model = Qt.createQmlObject("import QtQuick 2.12; ListModel {}", parent);
                    for(var i = 0; i < 100; i++){
                        model.append({"text": ""});
                    }
                    model
                }
                delegate: Item {
                    width: parent.width
                    height: 40
                    visible: index >= listView2.currentIndex - 5 && index <= listView2.currentIndex + 5
                    Text {
                        text: modelData.text
                        anchors.fill: parent
                        horizontalAlignment: Text.AlignHCenter
                        verticalAlignment: Text.AlignVCenter
                    }
                }
            }
            Component.onCompleted: {
                var generator = new RandomDataGenerator();
                generator.dataGenerated.connect(function(data){
                    RandomDataGenerator.onDataGenerated(data, 2);
                });
                generator.start();
            }
        }
    }
}

2.C++部分:

我们创建了一个简单的QML应用程序,用于展示一个包含1000个项目的列表。我们使用了ListView和ListModel来实现列表视图,并通过JavaScript代码来生成随机数据。我们还使用了Qt Quick Compiler来编译QML代码,以提高应用程序的启动速度。

为了进一步优化性能,我们使用了以下技术:

  1. 使用了QML中的懒加载机制,只有在需要显示时才会实例化列表项。

  2. 使用了QML中的异步加载机制,在后台线程中生成随机数据,以避免阻塞主线程。

  3. 在C++中使用了QThreadPool来管理线程池,以提高并发性能。

以下是完整的源码:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QThreadPool>
#include <QTimer>
#include "randomdatagenerator.h"

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

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // Register RandomDataGenerator class to QML
    qmlRegisterType<RandomDataGenerator>("com.example", 1, 0, "RandomDataGenerator");

    // Load QML file
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    // Start generating random data in background thread
    RandomDataGenerator generator;
    QThreadPool::globalInstance()->start(&generator);

    // Set up timer to update list view every 100ms
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&engine](){
        engine.rootObjects().first()->findChild<QObject*>("listView")->setProperty("currentIndex", 0);
    });
    timer.start(100);

    return app.exec();
}

RandomDataGenerator.h
 

#ifndef RANDOMDATAGENERATOR_H
#define RANDOMDATAGENERATOR_H

#include <QObject>
#include <QRunnable>
#include <QVector>

class RandomDataGenerator : public QObject, public QRunnable
{
    Q_OBJECT
public:
    explicit RandomDataGenerator(QObject *parent = nullptr);

signals:
    void dataGenerated(const QVector<QString>& data);

protected:
    void run() override;

private:
    QVector<QString> m_data;
};

#endif // RANDOMDATAGENERATOR_H

RandomDataGenerator.cpp

#include "randomdatagenerator.h"
#include <QThread>

RandomDataGenerator::RandomDataGenerator(QObject *parent) : QObject(parent)
{

}

void RandomDataGenerator::run()
{
    // Generate random data in background thread
    for(int i = 0; i < 1000; i++){
        QString data = QString::number(qrand());
        m_data.append(data);
    }

    // Emit signal to notify data generation complete
    emit dataGenerated(m_data);
}

在这个示例中,我们使用了分页加载,虚拟视图和异步加载来优化列表数据过多时切换tab的性能问题。当用户切换到某个tab时,只有当前页的数据会被加载并显示,而其他页的数据不会被实例化。这样可以减少初始加载时间和内存占用,并提高切换tab的速度。

以下是一个简单的示例代码,展示了C++向qml传递大量数据可能导致卡顿情况: MyObject.h: ```cpp #ifndef MYOBJECT_H #define MYOBJECT_H #include <QObject> #include <QVector> class MyObject : public QObject { Q_OBJECT public: explicit MyObject(QObject *parent = nullptr); signals: void dataReady(const QVector<int>& data); public slots: void processData(); private: QVector<int> m_data; }; #endif // MYOBJECT_H ``` MyObject.cpp: ```cpp #include "MyObject.h" MyObject::MyObject(QObject *parent) : QObject(parent) { } void MyObject::processData() { for(int i = 0; i < 1000000; i++) { m_data.append(i); } emit dataReady(m_data); } ``` main.cpp: ```cpp #include <QGuiApplication> #include <QQmlApplicationEngine> #include "MyObject.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; qmlRegisterType<MyObject>("MyObject", 1, 0, "MyObject"); MyObject object; QObject::connect(&object, &MyObject::dataReady, [&](const QVector<int>& data){ engine.rootContext()->setContextProperty("data", QVariant::fromValue(data)); }); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; object.processData(); return app.exec(); } ``` 上述代码中,MyObject类的processData()函数在程序启动时被调用,它qml界面传递一个包含1000000个整数的QVector,这可能导致界面卡顿。 为了解决这个问题,可以参考我的前面的建议,对数据传输方式、qml界面显示和C++数据处理逻辑进行优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值