【qml】QML最佳实践01


QML 和 Qt Quick拥有许多优点,但在某些情况下,也有一些点需要注意。本文将描述在Qt QML开发中的三个最佳实践方法。

一、自定义UI控制元素

现如今,流畅、现代、高端大气的UI是目前任何一个应用程序成功的关键,这一点,也是QML对设计人员或开发人员意义重大的地方。在实的应用程序开发中,Qt提供了最基本的UI控件,这些控件是创建一个流畅和现代的UI所必需的东西。因此,当在我们的实际工程开发中,应事先浏览一下Qt提供的控件,如果没有符合我们自己的需求效果的,我们才去创建自定义的控件。(如何创建自定义控件,后续小生会写一篇来描述其大致过程和思路)


我们可以通过以上“字母索引”寻找查看需要的QML类型。

二、将UI与逻辑分离

在我们实际应用程序开发过程中,为了创建可维护的应用程序,需要分离用户界面与业务逻辑。QML对UI的设计和开发有着较好的支持,主要有以下三点原因:

(1)QML属于声明性语言,它非常适合用于描述UI,因为UI元素之间往往呈现嵌套和级联的特性。

(2)在QML中,我们可以很容易使用JavaScript来响应事件。

(3)相对于C++来说,QML代码编写要简单许多。

C++作为一种强类型语言,最适合应用程序的逻辑开发。通常,这类代码会去执行复杂的计算或数据处理等任务,使用C++来实现会比QML更快。

综上,QML适合用于用户界面的开发,C++适合用于程序逻辑(大量计算和数据处理等)的开发,在实际使用中,我们可以按照这个规则进行开发。

三、在C++中与QML交互

Qt允许我们从C++操作QML,但是不建议这样做。为了解释原因,让我们看一个简单的例子。

(3-1)在C++中提取QML引用

这里假设我们正在开发一个设置页面,其QML代码如下:

import QtQuick 2.15
import QtQuick.Controls 2.15

Page {
    Button {
        text: qsTr("Restore")
    }
}

这个时候,我们希望按钮在被单击时在C++中做一些事情。我们知道QML中的对象可以像在C++中一样发出更改信号,所以我们给按钮定义一个objectName,这样我们就可以从C++中找到QML中的按钮:

Button {
    objectName: "restoreButton"
    text: qsTr("Restore")
}

然后,在C++代码中,我们找到该对象并连接到它的更改信号:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QSettings>

class LogicHandle : public QObject
{
    Q_OBJECT

public:
    LogicHandle() {}

public slots:
    void restoreDefaults() {
        settings.setValue("loadLastProject", QVariant(false));
    }

private:
    QSettings settings;
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

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

    LogicHandle backend;

    QObject *rootObject = engine.rootObjects().first();
    QObject *restoreDefaultsButton = rootObject->findChild<QObject*>("restoreButton");
    QObject::connect(restoreDefaultsButton, SIGNAL(clicked()),
        &backend, SLOT(restoreDefaults()));

    return app.exec();
}

上述代码中,在C++中通过objectName找到了QML中的按钮,然后使用connect()函数进行按钮点击信号和槽函数的关联。那么,使用这种方式让QML与C++之间进行交互会有一个问题:

C++逻辑层依赖于QML表示层。

如果当我们改变了objectName,或者由于某些原因造成C++查找QML对象逻辑破坏,这时候我们需要修改的地方就变得非常的多(QML和C++都需要修改)且代码之间的变得高度耦合,这将是一件无趣且糟糕的事情!

因此,为了避免这种问题的出现,在QML与C++进行交互的时候,可以使用下文所述的方法:将C++类对象注册到QML中

(3-2)将C++类对象注册到QML中

重构QML比重构C++要容易得多,所以为了让维护变得轻松,我们应该尽量让C++类型不知道QML。这可以通过将对C++类型的引用“推”到QML中来实现:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    LogicHandle backend;

    QQmlApplicationEngine engine;
    
    //将LogicHandle类的实例backend注册到QML上下文中
    engine.rootContext()->setContextProperty("backend", &backend);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

然后在QML直接调用C++槽函数:

import QtQuick 2.15
import QtQuick.Controls 2.15

Page {
    Button {
        text: qsTr("Restore")
        onClicked: backend.restoreDefaults()
    }
}

在上述代码中,对于按钮的点击事件处理则放到了QML中,且在QML中通过注册的C++类访问到其槽函数。

使用这种方法,即使将来QML代码可能会需要重构,但是C++代码是不会受到任何影响的。

四、总结

本文似乎是更倾向于经验性总结的文章,描述了在QML开发中的三个最佳实践方式:

(1)在自定义QML控件之前我们应该做的事情——查找、检索、验证Qt官方提供的QML类型;

(2)UI和逻辑分离的开发方式:QML适合用于用户界面的开发,C++适合用于程序逻辑(大量计算和数据处理等)的开发;

(3)在C++中与QML交互,虽然该种方式不推荐使用,但也是值得了解的。推荐在QML中与C++交互

对于QML来说,经小生多个版本的使用对比得出一结论:强烈推荐使用Qt 5.13版本以上的QML,过低的QML版本就不要去用了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iriczhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值