首页 > 其他分享 >Qt元对象语言

Qt元对象语言

时间:2023-12-28 15:03:24浏览次数:23  
标签:语言 绑定 Qt 对象 元素 QML 组件 id 属性

1. QML (Qt Meta-Object Language,Qt元对象语言)

QML是一种基于CSSJavaScript,用于描述对象间关系声明式语言。其属性部分是CSS风格的键值对,行为部分则使用JavaScript实现。

注:QML是Qt Meta-Object Language,而不是Qt Markup Language的缩写。

Image {
    id: root
    ...
    MouseArea {
        anchors.fill: parent
        onClicked: wheel.rotation += 90
    }
    ...
}

1.1. 元素

元素是构建QML应用的基本构件的模板。

  • 每个QML文件都有且只有一个根元素
  • 元素由其类型加{}声明
  • 元素可以有属性,通过name: value形式使用
  • 通过id可以访问QML文档中的任意元素
  • 元素可以嵌套,关键字parent用于访问父元素
import QtQuick

// 以Rectangle为根元素
Rectangle {
    // 命名此元素为root
    id: root

    // 属性: <键>: <值>
    width: 120; height: 240

    // color属性
    color: "#4A4A4A"

    // 定义一个嵌套元素 (root的子元素)
    Image {
        id: triangle

        // 引用父元素
        x: (parent.width - width)/2; y: 40

        source: 'assets/triangle_red.png'
    }

    // root的其它子元素
    Text {
        // 匿名元素

        // 通过id引用元素
        y: triangle.y + triangle.height + 20

        // 引用根元素
        width: root.width

        color: 'white'
        horizontalAlignment: Text.AlignHCenter
        text: 'Triangle'
    }
}

通常情况下,使用root作为根类型id


1.2. 属性

元素通过其元素名称声明,通过使用属性或创建自定义属性来定义。属性是一个有明确类型、可以有默认值的简单键值对。

Text {
    // (1) 标识符
    id: thisLabel

    // (2) 设置x, y坐标
    x: 24; y: 16

    // (3) 绑定 height 为 2 * width
    height: 2 * width

    // (4) 自定义属性
    property int times: 24

    // (5) 属性别名
    property alias anotherTimes: thisLabel.times

    // (6) text属性包含一个值
    text: "Greetings " + times

    // (7) 字体是分组属性
    font.family: "Ubuntu"
    font.pixelSize: 24
    // font { family: "Ubuntu"; pixelSize: 24 }

    // (8) KeyNavigation是附加属性
    KeyNavigation.tab: otherLabel

    // (9) 属性变化信号处理程序
    onHeightChanged: console.log('height:', height)

    // focus属性表示是否接收按键事件
    focus: true

    // 依赖focus属性改变颜色
    color: focus ? "red" : "black"
}

1.2.1. id

id是由QML语法定义,不可重置,用于引用QML文件内元素的唯一标识符。(1)

1.2.2. 属性设置

属性可以设置成与其类型相关的值。如果没有设置,则为初始值。 (2)

1.2.3. 绑定

  • 属性绑定 属性可以依赖一个或多个属性。绑定属性会随其依赖属性变化而变化。 (3)

  • 表达式绑定 属性还可以依赖表达式。绑定属性会随依赖表达式变化而变化。 (6)

1.2.4. 自定义属性

通过属性限定符按如下格式添加自定义属性:

  • property <类型> <名称>: <初始值>

其中初始值可选,如果没有初始值,将会使用默认初始值。 (4)

1.2.5. 默认属性

通过default关键字声明一个属性为默认属性。如果子元素未明确绑定到某个属性,则该元素将绑定到默认属性。

1.2.6. 别名

通过以下方式将对象属性或对象本身从类型内部转发到外部作用域:

  • property alias <名称>: <引用>

通过别名,我们可以将内部属性、元素id输出到根级别。别名声明不需要类别,它使用引用的属性或对象类型。 (5)

1.2.7. 分组属性

当一个属性结构比较复杂时,就会用到分组属性。 (7)

1.2.8. 附加属性

有些属性属于元素类本身。这种属性适用于在应用程序中只出现一次的全局设置元素。 (8)

  • <元素>.<属性>: <值>

1.2.9. 信号处理程序

每个属性都可以拥有一个信号处理程序。信号处理程序将在属性发生变化后调用。 (9)


1.3. 脚本

QML与JavaScript(ECMAScript)关系密切。

Text {
    id: label

    x: 24; y: 24

    // 自定义属性记录空格键按压次数
    property int spacePresses: 0

    text: "Space pressed: " + spacePresses + " times"

    // (1) text变化处理程序需要使用函数来捕获参数
    onTextChanged: function(text) { 
        console.log("text changed to:", text)
    }

    // 接收按键事件
    focus: true

    // (2) 使用JavaScript处理
    Keys.onSpacePressed: {
        increment()
    }

    // 退出键按下时清空
    Keys.onEscapePressed: {
        label.text = ''
    }

    // (3) JavaScript函数
    function increment() {
        spacePresses = spacePresses + 1
    }
}

1.3.1. 函数语法的处理程序

通过函数语法处理程序能够接收信号传递的参数。通常有以下两种形式:

  • function(args...) {} (1)
  • 箭头函数((args...) => {})

第一种更易于阅读,因此使用更为广泛。

1.3.2. 调用JavaScript函数

需要使用JavaScript函数处理时,直接调用即可。 (2)

1.3.3. JavaScript函数定义

JavaScript函数以如下形式定义:

  • function <函数名>(<参数>) { ... } (3)

1.4. 绑定

QML绑定:与JavaScript赋值=的区别在于,绑定在其生命周期内一直生效,而赋值只生效一次。

1.4.1. 生命周期

绑定的生命周期持续到下一次赋值或绑定为止。

1.4.2. 重新绑定

通过如下方法为属性建立新的绑定:

  • <属性> = Qt.binding(<表达式>)

1.5. 组件

组件是可重复使用的元素。QML组件通常由组件文件(QML文件)定义,而Component元素能够在QML文件内嵌定义QML组件。 为了方便描述,我们将由文件定义的组件称为顶级组件(top-level component),由Component元素定义的组件称为内联组件(in-line component)注:描述可能过时,因为在最新的Qt文档中无此表达。

1.5.1. 顶级组件

一个QML文件即为一个组件,元素类型即文件名。并且,对于文件组件而言,只有根级别的属性才能被其它文件的组件访问。

1.5.2. 内联组件


2. QML扩展

QML运行时采用C++开发,并且可以通过C++来扩展运行时功能。


2.1. 运行时

运行时是QML的执行环境,它由QtQml模块提供。它由引擎、上下文、组件组成。其中

  • 引擎负责执行QML
  • 上下文保存每个组件可访问的全局属性
  • 组件表示可从QML实例化的QML元素。
#include <QtGui>
#include <QtQml>

int main(int argc, char **argv)
{
    QGuiApplication app(argc, argv);
    QUrl source(QStringLiteral("qrc:/main.qml"));
    QQmlApplicationEngine engine;
    engine.load(source);
    return app.exec();
}

2.2. 注册QML类型

将C++类型注册为QML类型,使得开发者能够在QML中控制C++对象的生命周期,并且不会污染全局命名空间。但是所有的类型都要先注册才能使用,因此所有库都需要在应用程序启动时就链接。 假设CurrentTime继承于QObject,则可通过以下方法将CurrentTime注册为QML类型,并在QML中使用:

QQmlApplicationEngine engine();

qmlRegisterType<CurrentTime>("org.example", 1, 0, "CurrentTime");

engine.load(source);
import org.example 1.0

CurrentTime {
    // 访问属性、方法、信号
}

2.3. 添加上下文属性

如果不需要在QML中实例化新类,则可以通过如下方式将C++对象添加到QML上下文属性中:

QScopedPointer<CurrentTime> current(new CurrentTime());

QQmlApplicationEngine engine();

engine.rootContext().setContextProperty("current", current.value())

engine.load(source);
import QtQuick
import QtQuick.Window

Window {
    visible: true
    width: 512
    height: 300

    Component.onCompleted: {
        console.log('current: ' + current)
    }
}

由于上下文属性的继承关系,添加到上下文属性的对象在QML代码的任何地方都可以使用。


2.4. QML扩展插件 (待完成)

QML扩展插件是比注册QML类型、上下文属性更加灵活的QML扩展方式。插件会在第一个QML文件导入标识符是加载,并在插件中注册类型。通过使用QML单例,不会污染全局命名空间。并且插件可以在不同的项目中重复使用。

当我们通过import关键字导入模块时,QML运行时会在QML导入路径中查找并加载这些模块。由此模块提供的新类型将提供给QML环境。

2.4.1. 插件内容

插件是一个可按需加载、具有指定接口的库。在QML中,插件接口由类QQmlExtensionPlugin提供。

2.4.2. 创建插件

标签:语言,绑定,Qt,对象,元素,QML,组件,id,属性
From: https://blog.51cto.com/u_15990474/9015059

相关文章

  • 统一大语言模型和知识图谱:如何解决医学大模型-问诊不充分、检查不准确、诊断不完整、
    统一大语言模型和知识图谱:如何解决医学大模型问诊不充分、检查不准确、诊断不完整、治疗方案不全面?医学大模型问题如何使用知识图谱加强和补足专业能力?大模型结构知识图谱增强大模型的方法 医学大模型问题问诊。偏离主诉和没抓住核心。解决方案:建立抗干扰的能力,使得发现用户问题......
  • 多态在不同语言间是如何实现的?
    先说结论:多态是一种思路概念。不同的语言实现方式不太一样。大致分为两种。1.接口实现 接口实现,是用于静态语言中。特点是只声明。2.继承实现。继承实现,是动态语言中。特点是,父类写个基本的,子类重写父类。就是覆盖着写,来实现。举例:java中的接口示例:interfaceA......
  • 2_C#语言基本类型
    C#语言中常见的类型预定义简单类型名称含义默认值sbyte8位有符号整数0byte8位无符号整数0short16位有符号整数0ushort16位无符号整数0int32位有符号整数0uint32位无符号整数0long64位有符号整数0ulong64为无符号整数0float(I......
  • 遇到跨端开发或多项目开发时,遇到的一些问题探讨,后端开发语言如何选择?
    ​ 最近有同学问我,做后端开发项目时用php,java,c#,go,pathon...哪个好,从最近阿里云、美团服务器崩溃来看,我想给你最直接的回答是,没有完美的,只有适合自己的。咱们讨论最多的问题就是跨多端开发,以及多项目开发后期所带来的升级、维护等相关问题,接下来就该问题,我发表一点自己的看法,也算是......
  • MQTT连接远程MQTT服务器
    MQTT连接远程MQTT服务器本篇文章以SpringBoot项目为主进行介绍连接步骤。1、首先需要给定远程MQTT服务器的地址BrokerAddr:远程地址(域名):18831883端口号在TCP/IP协议中被用于MQTT通信。既然用到MQTT,我们一般都是用来将设备的数据进行上传到云平台进行展示的。因此我们还需......
  • Amazon Lex揭示大语言模型与生成式AI的未来发展
    AmazonLex的产品经理MarceloSilva与总经理GaneshGeller以及洛克希德·马丁公司的研究员和首席架构师GregDoppelhower在re:Invent开发者大会中分享了关于大语言模型与生成式AI的最新进展。演讲强调了如何利用AmazonLex以及与AmazonConnect的完全集成平台,为员工和客户创造个性......
  • 超时控制:Go语言下的网络请求与时间赛跑
    开场白:在互联网的世界里,我们经常要与各种API打交道。有时,这些API可能会因为各种原因而变得“慢条斯理”,这时,超时控制就显得尤为重要了。今天,我们就来聊聊如何在Go语言中实现HTTP请求的超时控制,与时间赛跑!知识点一:了解超时控制的必要性想象一下,当你正在等待一个重要的API响应时,如果......
  • 跨域请求:Go语言下的“通天大道”
    开场白:嘿,各位Go语言的爱好者们,你们是否曾经遇到过这样的困扰:当你的Go应用试图与另一个域的API进行交流时,突然跳出一个“未允许的跨域请求”的警告?别担心,今天,我们将一起在这条“通天大道”上漫步,解决跨域的困扰!知识点一:何为跨域问题?简单来说,当你在浏览器中访问一个网页,该网页试图从......
  • HTTP代理服务器:Go语言下的“网络翻译官”
    开场白:在这个全球化的网络时代,有时我们需要一个“翻译官”来帮助不同系统、不同语言进行交流。今天,我们就来探讨如何使用Go语言,轻松实现这样一个角色——HTTP代理服务器,让我们的网络请求更加畅通无阻!知识点一:什么是HTTP代理服务器?想象一下,你是一名只会说中文的游客,身处一个只会说英......
  • 处理HTTP错误响应:Go语言中的稳健之道
    开场白:在Web开发中,HTTP错误响应是不可避免的一部分。当请求无法成功完成时,服务器会返回一个错误响应。今天,我们将深入探讨如何在Go语言中优雅地处理这些HTTP错误响应。知识点一:HTTP错误响应的常见类型HTTP错误响应通常由状态码和相应的消息组成。常见的状态码包括:404(未找到)、500(内......