QML面试常见问题(一)QML中组件呈现方式的方法有哪些

前言

本文主要想要记录面试时可能会被问到的一些qml常见问题,帮助面试前快速复习和回顾。

由于是记录文章,所以会不断往后添加问题,必要时会另开新文章。

一、QML中组件呈现方式的方法有哪些?

1.基础属性绑定(最直接的 UI 数据呈现)

这是 QML 的基石。无论是 QML 内部的 property 还是从 C++ 暴露过来的对象属性,只要把 UI 组件的属性(如 text)和它进行绑定,数据一变,界面自动刷新。

cpp 复制代码
import QtQuick
import QtQuick.Controls

Window {
    width: 400; height: 200; visible: true
    title: "基础属性绑定"

    // 1. 在 QML 内部定义属性变量
    property string statusText: "等待操作..."
    property int clickCount: 0

    Column {
        anchors.centerIn: parent
        spacing: 20
        // 2. 直接将属性绑定到组件上
        Label { text: statusText; font.pixelSize: 20 }
        
        Button {
            text: "点击我"
            onClicked: {
                clickCount++
                // 修改属性,界面上的 Label 会自动更新
                statusText = "按钮已被点击 " + clickCount + " 次"
            }
        }
    }
}

注:如果是 C++ 交互,你只需要把 statusText 换成从 C++ 注册进来的单例对象属性(如 cppBackend.statusText)即可,绑定语法完全一致。

2.绑定C++侧对象属性

这部分是上述方法的补充,详情可以回看之前学习记录的博客文章。

核心思想是将C++元素暴露给qml侧,让它能够进行调用。这里主要分为几种思路。
(1)上下文属性暴露

通过以下接口,我们可以将某个属性暴露给qml侧。

cpp 复制代码
QString lastName = "Doe";
QString firstName = "John";

engine.rootContext()->setContextProperty("lastname", QVariant::fromValue(lastName));
engine.rootContext()->setContextProperty("firstname", QVariant::fromValue(firstName));

可以看到,这种方式并没有创建什么c++实例对象,单纯只是将一个变量注册暴露给qml。另外,传参的名字类似别名,可以和原变量名不一样。

但上下文属性暴露同样支持暴露实例对象,

cpp 复制代码
CppClass1 cppclass1;
engine.rootContext()->setContextProperty("CppClass1",&cppclass1);

这种方法也是给类实例对象取别名,其公共接口使用Q_INVOKABLE 修饰后,可在qml中直接被调用。而信号不需要修饰也可以用。

重点来了,如果需要使用其变量,我们需要先在头文件声明中,对某个成员变量进行Q_PROPERTY属性声明。

这里的成员变量和Q_PROPERTY声明的属性,本质上不是绑定关系,是因为我们在该属性的具体方法(读写、通知)中调用了成员变量,故形成了绑定关系。此后,在qml中调用该属性,就相当于绑定了成员变量。如:text: xxx.name

(2)上下文对象暴露

和上述的方法类似,但这种方法暴露实例对象的时候,不需要取别名,qml使用的时候没有名字修饰,直接引用属性(变量)名(需要Q_PROPERTY修饰),这看上去比较精简方便,但有命名冲突的风险。

个人不推荐这种方式,如果需要单例,我们可以使用qmlRegisterSingletonInstance的方式
(3)单例

略。详情看博客文章。

3.信号槽

qml中同样支持信号槽的方式。

如果想要在qml中呈现数据,可以在qml中接收某个c++对象的信号。

方法大概如下,首先,我们需要对c++某个实例对象进行属性暴露,然后在qml中Connections中实现槽函数。具体实现类似如下:

cpp 复制代码
    Connections{
        target: CppSignalSender

        onCallQml: function(parameter){
            console.log("This is QML: callQml signal cought:")
            mText.text = parameter
        }

        onCppTimer: function(value){
            mRectText.text = value
        }
    }

4.ListView中呈现数据

由于面试官问到过这个,我就记录一下。(相关笔记55-57)

实际上,在qml中,这是比较典型的model-view结构,还涉及到delegate的概念。

我不想过多展开,简单来说,view即视图层的组件,即listview,model是数据来源,而delegate则是委托,它比较抽象,除了决定ui样式,还可以决定数据的表现方式。

比如model的一项数据(listelement)里面有name和price两个属性,而delegate可以决定呈现方式为rectangle里内嵌一个文本,文本绑定了:name+"---"+price。这是相当灵活的表现形式。

listview对应的就是listmodel,有关model的定义形式比较丰富,较为正式的是这种,ListElement是其中一个元素:

cpp 复制代码
 ListModel{
        id: modelId
        ListElement{
            country:"China"
            capital: "BeiJing"
        }
        ListElement{
        // ...
        }
    }

还有就是这种内联定义的方式:

cpp 复制代码
model: ["January",
            "February",
            "March",
            "April",
            "May",
            "June",
            "July",
            "August",
            "September",
            "October",
            "November",
            "December"]

方式有很多,但这种方式的数据来源都是qml。

如果想要从c++侧获取数据来源,可以在那边定义model,然后通过属性暴露的方式,进行绑定。又或者通过信号槽的方式发送过来。虽然还没有验证过,但应该是可以的。

相关推荐
烛衔溟13 小时前
HarmonyOS 基础 UI 构建 —— 组件、布局与沉浸式效果
ui·华为·harmonyos
吴阿福|一人公司13 小时前
类变量和实例变量的命名规范有哪些避坑点?
开发语言·python
Aaswk13 小时前
Java项目:文件批量处理工具
java·开发语言·vscode·idea
小江的记录本14 小时前
【Spring全家桶】Spring AI核心原理、大模型集成、Prompt工程、RAG实现、AI Agent开发(附《思维导图》+《面试高频考点清单》)
java·人工智能·spring boot·后端·spring·面试·prompt
EMA14 小时前
Agent开发中数据分析图表工具分层暴露方案总结
面试
稷下元歌14 小时前
七天学会plc加机器视觉之AI 接入 外设模块开发全详细操作文档(全程配套视频按文档实操)
python·sql·qt·贪心算法·r语言·wpf·时序数据库
晚风吹红霞14 小时前
深入浅出 STL 之 map 与 set:从入门到实战
开发语言·c++
牛油果子哥q14 小时前
【C++封装】C++封装思想与访问权限终极精讲:public/private/protected权限解析、类封装设计、继承权限变化、工程私有化规范与面试坑点
c++·面试
织梦旅途14 小时前
C++ 第一课 从 Hello Word!立刻开始
c++
.千余14 小时前
【C++】 String 常用操作:增删查改 | 查找 | 截取 | IO
java·服务器·开发语言·c++·笔记·学习