组件声明以及设置属性
所有的组件的基类为:QtObject,在c++中名称为:QObject。
在qml和c++名称有所区别,例如在Qml中QtObject,在C++会省略一个t(QObject)
声明组件的方式:
组件名 {属性名:值}
在实际应用中:
import QtQuickWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")//声明Text组件Text{text:"Text组件"}
}
组件属性类型:
- id属性
- 枚举属性
- 自定义属性
- 组件属性
- JavaScript方法
- 信号属性
- 信号处理程序
- 附加属性和附加信号处理程序
id属性
Qml 组件只能拥有一个 id 属性,可以用于数据的绑定。
import QtQuick
import QtQuick.LayoutsWindow {id: windowwidth: 400height: 300visible: truetitle: qsTr("Hello World")
}
给窗口的id属性赋予window。
枚举属性
枚举提供一组固定的命名选择。可以在 Qml 中使用关键字声明: enum
Text {enum TextType {Normal,Heading}
}
自定义属性
在组件中自行定义的属性称为自定义属性或者扩展属性,自定义属性名称必须以小写字母开头,并且只能包含字母、数字和下划线。
[default] [required] [readonly] property <propertyType> <propertyName>
default 默认属性
组件可以拥有一个默认属性(仅一个)。默认属性是一种非常实用的特性,它允许组件在实例化时,将未明确指定属性名的子元素自动关联到该默认属性,从而简化代码编写。
使用可选关键字 default 声明属性会将其标记为默认属性
default property <propertyType> <propertyName>
default property 属性类型 属性名
示例:
// 自定义组件 MyComponent.qml
Item {// 声明默认属性,类型为Item(可以是任意类型)default property Item content// 使用默认属性Component.onCompleted: {console.log("默认属性内容:", content)}
}
MyComponent {// 这里的Text没有指定属性名,会自动赋值给contentText { text: "这会成为默认属性的值" }
}
声明MyComponent 组件,并赋予子组件Text 给MyComponent ,Text 组件会自行存储到content默认属性中。
上面的代码等价于:
MyComponent {content: Text { text: "这会成为默认属性的值" }
}
常见使用场景
1. 容器类组件(最典型用法)
Qt 自带的 Column 、 Row 、 ListView 等容器组件都使用了默认属性,让子元素的添加更自然:
Column {// 这些Text会自动添加到Column的默认属性children中Text { text: "Item 1" }Text { text: "Item 2" }
}
( Column 的默认属性实际是 children ,用于存储子元素列表)
2. 自定义容器组件
// Card.qml - 卡片组件
Rectangle {color: "white"border.width: 1radius: 4// 声明默认属性,用于接收卡片内容default property Item cardContent// 布局默认属性内容Column {anchors.fill: parentanchors.margins: 10// 显示默认属性内容Loader { sourceComponent: cardContent }}
}// 使用Card组件
Card {// 这里的内容会自动成为cardContentText { text: "卡片标题" }Text { text: "卡片内容..." }
}
3. 处理列表类型的默认属性
默认属性也可以是列表类型,用于接收多个子元素:
Item {// 声明列表类型的默认属性default property list<Item> itemsColumn {// 显示所有默认属性中的元素Repeater {model: itemsdelegate: Loader { sourceComponent: modelData }}}
}
// 使用时可以直接添加多个子元素
MyList {Text { text: "第一个元素" }Text { text: "第二个元素" }Text { text: "第三个元素" }
}
注意事项
- 一个组件只能有一个默认属性
- 默认属性可以是任意类型(基本类型、对象、列表等)
- 如果同时存在显式赋值和默认赋值,显式赋值会覆盖默认赋值
- 通常用于容器类组件,但也可用于需要简化赋值的任何场景
required 必填属性
定义一个不可为空的属性,简称必填属性。
required property <propertyType> <propertyName>
required property 属性类型 属性名
示例:
// 自定义组件 UserCard.qml
Rectangle {// 声明必填属性(姓名和年龄为必需)required property string userNamerequired property int userAge// 使用这些属性Text {text: `姓名: ${userName}, 年龄: ${userAge}`anchors.centerIn: parent}
}
使用带必填属性的组件:
// 正确用法:提供了所有必填属性
UserCard {userName: "张三"userAge: 30width: 200height: 80
}// 错误用法:缺少必填属性(会抛出运行时错误)
UserCard {// 缺少 userName 和 userAge,QML引擎会报错width: 200height: 80
}
readonly 只读属性
required对象声明可以使用关键字定义只读属性,语法如下:readonly
readonly property <propertyType> <propertyName> : <value>
readonly property 属性类型 属性名 : 值
组件属性
不同的组件具有不同的属性。例如:Text组件的text属性控制界面显示的文本内容。
在Qml中所有的组件都基于QtObject,QtObject却仅有一个属性(objectName),在使用组件时必须了解组件的继承关系。
因为所有组件都是基于QtObject,所以组件都拥有QtObject的objectName属性。
Text组件的继承关系:QtObject->Item->Text
JavaScript方法
JavaScript方法是可以调用该函数来执行某些处理或触发进一步的事件。
function <functionName>([<parameterName>[: <parameterType>][, ...]]) [: <returnType>] { <body> }
//不带参数
function 方法名():返回类型{语句块}//带参数
function 方法名(参数名:参数类型){语句块}//带参数,带返回值
function 方法名(参数名:参数类型):返回类型{语句块}
示例:
import QtQuick
Rectangle {id: rectfunction calculateHeight(): real {return rect.width / 2;}width: 100height: calculateHeight()
}
信号属性以及信号处理程序
在 Qml 中,信号(Signal)是组件间通信的核心机制,允许一个组件在特定事件发生时发出通知,其他组件可以 “连接”(connect)到这个信号并做出响应。信号本身不是传统意义上的 “属性”,但可以理解为组件对外暴露的一种 “事件接口”,用于触发外部逻辑。
信号的本质
- 信号是组件定义的 “事件触发器”,当特定条件满足时(如按钮被点击、数据变化等)会被 “发射” 信号
- 其他组件可以通过 “信号处理程序”(Signal Handler)或代码连接来响应信号
- 信号可以携带参数,用于传递事件相关的数据
使用 signal 关键字声明信号:
// 自定义组件 MyButton.qml
Rectangle {id: rootwidth: 100height: 30color: "lightblue"// 声明一个无参信号signal clicked// 声明一个带参数的信号signal textChanged(string newText, string oldText)Text {id: labelanchors.centerIn: parenttext: "Click Me"}MouseArea {anchors.fill: parentonClicked: {// 发射信号(触发事件)root.clicked()root.textChanged("Clicked!", label.text)}}
}
示例代码中, MouseArea 是 Qt Quick 提供的一个内置组件,专门用于处理鼠标和触摸事件。
信号处理程序
使用组件时,通过 on 语法定义信号处理器(首字母大写):
MyButton {// 响应无参信号onClicked: {console.log("按钮被点击了!")}// 响应带参数的信号onTextChanged: {console.log(`文本从 ${oldText} 变为 ${newText}`)}
}
动态响应信号
也可以在 JavaScript 中动态连接信号与处理函数。
MyButton {id: myBtnComponent.onCompleted: {// 动态连接信号myBtn.clicked.connect(handleClick)myBtn.textChanged.connect(handleTextChange)}function handleClick() {console.log("动态连接:按钮被点击")}function handleTextChange(newText, oldText) {console.log(`动态连接:文本变化 ${oldText} -> ${newText}`)}
}
信号与属性的关联
虽然信号不是属性,但 QML 的属性系统会自动为属性生成 “变化信号”(Change Signal):
- 当属性值发生变化时,会自动发射 onChanged 信号
- 例如 property string name 会自动生成 onNameChanged 信号
Item {property string userName: "默认名称"// 响应属性变化信号(自动生成)onUserNameChanged: {console.log(`用户名变为:${userName}`)}Button {text: "修改名称"onClicked: userName = "新名称" // 修改属性会触发信号}
}
核心特点
- 松耦合通信:信号发射方不需要知道谁在接收,接收方也不需要知道信号来源
- 多连接支持:一个信号可以连接多个处理函数
- 参数传递:通过信号参数传递数据,灵活传递事件上下文
- 自动生成:属性自动生成变化信号,简化状态监听
信号是 QML 中实现组件交互、状态管理的核心机制,广泛用于 UI 交互(如按钮点击、列表项选择)、数据流转(如模型更新通知)等场景
附加信号属性以及附加信号处理程序
在 QML 中,附加属性(Attached Properties)是一种特殊的属性机制,允许一个组件为另一个组件添加额外的属性,而无需修改被添加组件的原始定义。这些属性由一个 “附加类型” 提供,通过 <附加类型>.<属性名> 的语法使用。
附加属性的核心作用是:在不侵入组件内部实现的前提下,为其添加特定场景下的额外功能或数据。
基本用法与示例
最常见的附加属性来自 Qt Quick 的内置类型,例如 Item 的 Layout 附加属性(用于布局)、 Component 的 ApplicationWindow 附加属性等。
示例1:
在 Row 、 Column 等布局中, Layout 附加类型为子元素提供布局相关的附加属性:
import QtQuick 2.15
import QtQuick.Layouts 1.15Row {spacing: 10Rectangle {color: "red"width: 50height: 50// Layout.alignment 是附加属性,控制在布局中的对齐方式Layout.alignment: Qt.AlignCenter}Rectangle {color: "blue"width: 50height: 80// Layout.fillHeight 是附加属性,控制是否填充布局高度Layout.fillHeight: true}
}
这里 Layout.alignment 和 Layout.fillHeight 并非 Rectangle 自身的属性,而是 Layout 类型为 Rectangle 附加的布局属性。
示例2:
Window 类型提供的附加属性可用于控制子元素在窗口中的行为:
import QtQuick 2.15
import QtQuick.Controls 2.15ApplicationWindow {id: mainWindowwidth: 400height: 300title: "附加属性示例"Text {// Window.title 是附加属性,绑定到窗口标题text: "当前窗口标题: " + Window.title// Window.visibility 是附加属性,反映窗口可见性状态onWindowVisibilityChanged: {console.log("窗口可见性变化: ", Window.visibility)}}
}
附加属性的工作原理
- 定义一个 “附加类型”(通常是一个 QML 类型或 C++ 注册的类型)
- 该类型提供 attachedProp erties ,用于为其他组件附加属性
- 使用时通过 <附加类型>.<属性名> 的语法访问,QML 引擎会自动关联到目标组件
代码编写规范(建议)
qml的组件声明规范(使用text组件示例):
Text {id:text1 //声明组件ID(唯一)//可选,枚举类型enum TextType {Normal,Heading}//可选,声明自定义属性,(属性名首字母必须小写)property string label//可选,声明javascript 方法function calculateHeight(): real {return text1 .width / 5;}//设置外观属性width:100 //声明宽度height:calculateHeight() //声明高度anchors.verticalCenter: parent.verticalCenter //可选,锚点(anchors)布局设置//声明组件的内容属性text:"Text组件"//声明信号(信号用于组件的通知,表示某些事件已经发生)signal clicked //声明信号处理程序MouseArea {anchors.fill: parent }
}
组件属性赋予顺序 :
- id属性
- 枚举属性
- 自定义属性
- 组件属性
- JavaScript方法
- 信号属性
- 信号处理程序
- 附加属性和附加信号处理程序
以上的属性编写顺序是为之后方便阅读。(没有硬性要求,只为方便查看)