详细介绍:QML开发:QML中的基本元素

一、概述

  在 QML 中,基本元素(Basic Elements) 是构建 UI 界面的核心组件。QML 采用声明式语法,通过这些元素定义界面结构、行为和交互。元素可以被分为可视化元素与非可视化元素。一个可视化元素(例如矩形框Rectangle)有着几何形状并且可以在屏幕上显示。一个非可视化元素(例如计时器Timer)提供了常用的功能,通常用于操作可视化元素。

二、常用基本元素

2.1 基础视觉元素(常用于布局和显示)

在这里插入图片描述

2.1.1 元素 Item 的介绍和使用

  在 QML 中,Item 是最基础的可视元素之一,许多其他图形元素(如 Rectangle、Image、Text 等)都直接或间接继承自 Item。它本身不绘制任何内容,但可以用于组织、布局和管理子项。

基本介绍:

Item {
id: rootItem
width: 200
height: 100
}
  • Item 代表一个矩形区域,它本身不可见。
  • 可以包含子元素,是容器型组件。
  • 具有基本的坐标属性(x, y, width, height,anchors 等)。
  • 常用于组合多个组件或布局结构中。

常用属性:
在这里插入图片描述
常见用途:
用作容器,组织子元素

Item {
width: 300; height: 100
Rectangle {
width: 100; height: 100; color: "red"
}
Rectangle {
x: 120
width: 100; height: 100; color: "blue"
}
}

用于布局锚定

Item {
width: 200; height: 200
Rectangle {
width: 50; height: 50; color: "green"
anchors.centerIn: parent
}
}

示例演示:

import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 400
height: 300
visible: true
title: qsTr("Item 示例")
// Item 是一个无可视外观的容器
Item {
id: container
width: 300
height: 200
anchors.centerIn: parent
// 第一个子元素
Rectangle {
width: 100
height: 100
color: "lightblue"
x: 0
y: 0
}
// 第二个子元素
Rectangle {
width: 100
height: 100
color: "lightgreen"
x: 120
y: 50
}
}
}

效果如下:
在这里插入图片描述

2.1.2 元素 Rectangle 的介绍和使用

  Rectangle 是 QML 中最常用的可视化元素之一,用于绘制一个矩形区域。它可以设置颜色、大小、圆角、边框、渐变、阴影等属性,常用于 UI 中的背景、按钮、面板等组件。

基本语法:

Rectangle {
width: 200
height: 100
color: "lightblue"
}

常用属性说明:
在这里插入图片描述
示例 1:简单矩形

Rectangle {
width: 150
height: 80
color: "orange"
}

示例 2:带边框和圆角

Rectangle {
width: 200
height: 100
color: "white"
radius: 10
border.color: "black"
border.width: 2
}

示例 3:渐变背景

Rectangle {
width: 200
height: 100
gradient: Gradient {
GradientStop { position: 0.0; color: "red"
}
GradientStop { position: 1.0; color: "yellow"
}
}
}

示例 4:响应点击

Rectangle {
width: 100
height: 100
color: "lightgray"
MouseArea {
anchors.fill: parent
onClicked: {
parent.color = "green"
}
}
}
2.1.3 元素 Image 的介绍和使用

  Image 是 QML 中用于显示图像的元素。它继承自 Item,可以加载本地图片或网络图片,支持缩放、填充模式、异步加载、缓存等功能。

基本语法:

Image {
source: "my_picture.png"
width: 100
height: 100
}

常用属性:
在这里插入图片描述
fillMode 填充模式:
在这里插入图片描述
示例 1:加载本地图片

Image {
source: "qrc:/images/logo.png"
width: 100
height: 100
fillMode: Image.PreserveAspectFit
}

示例 2:加载网络图片

Image {
source: "https://example.com/image.jpg"
asynchronous: true
cache: true
width: 200
height: 150
}

示例 4:点击更换图片

Image {
id: dynamicImage
source: "img1.png"
width: 100
height: 100
MouseArea {
anchors.fill: parent
onClicked: {
dynamicImage.source = "img2.png"
}
}
}
2.1.4 元素 Text 的介绍和使用

在 QML 中,Text 元素用于显示一段文本,是最基本的文字展示组件,具有强大的排版和样式能力。

基本语法:

Text {
text: "Hello, QML!"
font.pixelSize: 20
color: "black"
}

常用属性:
在这里插入图片描述
wrapMode 换行模式:
在这里插入图片描述
示例一:显示带样式的文本

Text {
text: "欢迎使用 QML!"
color: "#1684DF"
font.pixelSize: 24
font.bold: true
anchors.centerIn: parent
}

示例二:多行文本 + 自动换行

Text {
text: "这是一段很长的文本,用于测试自动换行是否有效。"
width: 200
wrapMode: Text.Wrap
}

示例三:超出省略显示(elide)

Text {
text: "这是一个超出显示宽度的文本"
width: 150
elide: Text.ElideRight
}

示例四:HTML 文本支持

Text {
text: "<b>加粗</b> <i>斜体</i> <font color='red'>红色</font>"
textFormat: Text.RichText
}

示例五:点击文本实现交互

Text {
id: clickableText
text: "点击我"
color: "blue"
MouseArea {
anchors.fill: parent
onClicked: {
clickableText.text = "你点击了我!"
}
}
}

2.2 交互元素(用于接收用户操作)

在这里插入图片描述

2.2.1 元素 MouseArea 介绍和使用

在 QML 中,MouseArea 是一个 用于处理鼠标交互的基础元素,常用于响应点击、按下、释放、移动等事件。

基本语法:

MouseArea {
anchors.fill: parent // 鼠标区域覆盖整个父项
onClicked: {
console.log("鼠标被点击了")
}
}

常用属性说明:
在这里插入图片描述

常用信号(事件):
在这里插入图片描述
示例:点击改变颜色

Rectangle {
width: 200; height: 200
color: "lightblue"
MouseArea {
anchors.fill: parent
onClicked: {
parent.color = "lightgreen"
console.log("点击了矩形")
}
}
}

示例:悬停改变鼠标样式

Rectangle {
width: 100; height: 100; color: "lightgray"
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: console.log("鼠标进入区域")
onExited: console.log("鼠标离开区域")
}
}

示例:获取鼠标位置

MouseArea {
anchors.fill: parent
onPositionChanged: {
console.log("鼠标位置:", mouse.x, mouse.y)
}
}
2.2.2 元素 FocusScope 的介绍和使用

  在 QML 中,FocusScope 是一个 专门用于组织焦点(Focus)管理的容器元素。当你在组件中有多个可以获取焦点的子项时,使用 FocusScope 可以更清晰地控制哪个子控件获取焦点,避免焦点混乱。FocusScope 继承自 Item,本身不会获得焦点,但它能确保它内部的某个元素获得焦点时,焦点不会被传递到 FocusScope 外部。

基本语法:

FocusScope {
Rectangle {
width: 200; height: 40; color: "lightblue"
TextInput {
id: input1
anchors.centerIn: parent
focus: true // 初始获得焦点
}
}
}

示例1:多个输入框

FocusScope {
width: 300; height: 100
Column {
spacing: 10
TextInput {
id: input1
width: 200; height: 30
placeholderText: "输入框 1"
focus: true
}
TextInput {
id: input2
width: 200; height: 30`在这里插入代码片`
placeholderText: "输入框 2"
}
}
}

说明:这个 FocusScope 确保焦点不会传递到它之外,而是在 input1 和 input2 内部管理。

示例2:在组件中封装 FocusScope

// MyInputField.qml
FocusScope {
width: 200; height: 40
Rectangle {
anchors.fill: parent
color: "white"; border.color: "gray"
TextInput {
id: input
anchors.fill: parent
anchors.margins: 4
focus: true
}
}
}
// main.qml
Column {
spacing: 20
MyInputField {
}
MyInputField {
}
}

说明:即使你复用了 MyInputField,FocusScope 也能确保每个组件内部焦点独立。

注意事项:

  • 不能仅靠 focus: true 管理多个控件焦点,需要用 FocusScope 做容器。
  • 使用 Keys.onPressed 等键盘事件时,焦点必须在某个 focus: true 的控件上。
  • 一个组件内部只能有一个主动获取焦点的控件,多个控件都设置 focus: true 会导致焦点冲突。
2.2.3 元素 Keys 介绍和使用

  在 QML 中,Keys 是一个 用于处理键盘事件的附加属性对象,可以附加到可获得焦点的元素(如 Item、TextInput、TextField 等)上,以响应键盘输入。

基本用途:

Item {
focus: true // 只有获得焦点的元素才能接收键盘事件
Keys.onPressed: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
console.log("回车键被按下")
event.accepted = true // 表示已处理该事件,阻止继续传播
}
}
}

常用信号:
在这里插入图片描述

常见按键常量(来自 Qt.Key_*):
在这里插入图片描述
示例:方向键控制方块移动

Rectangle {
width: 300; height: 300; color: "white"
Rectangle {
id: box
width: 50; height: 50; color: "blue"
x: 0; y: 0
focus: true
Keys.onPressed: {
const step = 10;
if (event.key === Qt.Key_Right) {
box.x += step;
} else if (event.key === Qt.Key_Left) {
box.x -= step;
} else if (event.key === Qt.Key_Up) {
box.y -= step;
} else if (event.key === Qt.Key_Down) {
box.y += step;
}
}
}
}

注意事项:

  • 必须设置 focus: true 才能接收键盘事件
  • 如果键盘事件被多个元素监听,优先处理具有焦点的元素
  • event.accepted = true 表示事件已处理,防止冒泡

示例:Tab 键切换焦点

TextField {
id: input1
focus: true
Keys.onPressed: {
if (event.key === Qt.Key_Tab) {
input2.forceActiveFocus()
event.accepted = true
}
}
}
TextField {
id: input2
}

示例:监听组合键(如 Ctrl + S)

Keys.onPressed: {
if (event.key === Qt.Key_S && event.modifiers & Qt.ControlModifier) {
console.log("Ctrl+S 被按下")
event.accepted = true
}
}

2.3 布局元素(用于排版、排列)

在这里插入图片描述

2.3.1 元素 Row 的介绍和使用

在 QML 中,Row 是一个非常常用的 可视化布局元素,用于将子元素按水平方向依次排列。

基本语法:

Row {
spacing: 10 // 子元素之间的间距
Rectangle { width: 50; height: 50; color: "red"
}
Rectangle { width: 50; height: 50; color: "green"
}
Rectangle { width: 50; height: 50; color: "blue"
}
}

常用属性:
在这里插入图片描述
示例1:简单的水平排列

Row {
anchors.centerIn: parent
spacing: 20
Rectangle { width: 80; height: 40; color: "lightblue"
}
Rectangle { width: 80; height: 40; color: "lightgreen"
}
Rectangle { width: 80; height: 40; color: "lightpink"
}
}

示例2:嵌套使用(Row + Column)

Column {
spacing: 10
Text { text: "用户名:"
}
Row {
spacing: 5
Text { text: "账号:"
}
TextField { width: 150
}
}
Row {
spacing: 5
Text { text: "密码:"
}
TextField { width: 150; echoMode: TextInput.Password
}
}
}

示例3:设置排列方向为从右到左

Row {
layoutDirection: Qt.RightToLeft
spacing: 10
Rectangle { width: 60; height: 40; color: "orange"
}
Rectangle { width: 60; height: 40; color: "yellow"
}
Rectangle { width: 60; height: 40; color: "gray"
}
}

特性说明:

  • Row 是 自动计算自身大小 的容器,默认高度为最高子项的高度,宽度为所有子项宽度之和加 spacing。
  • Row 不会自动换行。如果你需要换行布局,可以使用 Flow。
  • 子项可以通过 Layout.alignment 等属性进一步对齐(但前提是搭配 RowLayout 使用,而非 Row)。
2.3.2 元素 Column 的介绍和使用

  在 QML 中,Column 是一个 基础的布局容器元素,它会自动将子元素 按垂直方向(从上到下)依次排列,适合用于表单、列表、按钮组等竖向布局场景。

基本语法:

Column {
spacing: 10 // 子元素之间的间距
Rectangle { width: 100; height: 40; color: "lightblue"
}
Rectangle { width: 100; height: 40; color: "lightgreen"
}
Rectangle { width: 100; height: 40; color: "lightpink"
}
}

常用属性:
在这里插入图片描述
示例:简单的垂直排列

Column {
anchors.centerIn: parent
spacing: 12
Button { text: "开始"
}
Button { text: "暂停"
}
Button { text: "退出"
}
}

示例:表单布局(使用 Column 嵌 Row)

Column {
spacing: 10
anchors.centerIn: parent
Row {
spacing: 10
Text { text: "用户名:"
}
TextField { width: 150
}
}
Row {
spacing: 10
Text { text: "密码:"
}
TextField { width: 150; echoMode: TextInput.Password
}
}
Button {
text: "登录"
anchors.horizontalCenter: parent.horizontalCenter
}
}

Column 的局限性:

  • 不会自动适配父容器宽度:默认只包裹内容大小
  • 无法设置子项的对齐方式:所有子项默认左对齐,不能设置右对齐或居中(需手动处理)
  • 不支持 Layout.* 属性:想用自动填充、拉伸等特性时,应该用 ColumnLayout
2.3.3 元素 Grid 的介绍和使用

  在 QML 中,Grid 是一个用于 网格布局 的容器,它会将子元素按照指定的 行列数量 自动排列,类似于 HTML 的表格或 Excel 表格的布局效果。

基本语法:

Grid {
rows: 2
columns: 3
spacing: 10 // 子项之间的间距
Rectangle { width: 60; height: 40; color: "red"
}
Rectangle { width: 60; height: 40; color: "green"
}
Rectangle { width: 60; height: 40; color: "blue"
}
Rectangle { width: 60; height: 40; color: "orange"
}
Rectangle { width: 60; height: 40; color: "yellow"
}
Rectangle { width: 60; height: 40; color: "purple"
}
}

上面例子中,Grid 设定了 2 行 3 列。子项会从左到右,从上到下依次填入。
最终布局如下(颜色代表每个矩形):

| red | green | blue |
| orange | yellow | purple |

常用属性:
在这里插入图片描述
注意:rows 和 columns 至少设置一个,否则 Grid 无法正常布局。

示例:固定列数,自适应行数

Grid {
columns: 3
columnSpacing: 8
rowSpacing: 8
Repeater {
model: 10
Rectangle {
width: 50; height: 50
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1.0)
}
}
}

示例:制作按钮九宫格

Grid {
columns: 3
spacing: 6
Repeater {
model: 9
Button {
text: (index + 1).toString()
width: 80
height: 50
}
}
}

示例:Grid + Text + Image 布局(联系人)

Grid {
columns: 2
spacing: 10
Repeater {
model: 4
Rectangle {
width: 150; height: 60; color: "#e0e0e0"
Row {
anchors.fill: parent
anchors.margins: 8
spacing: 10
Image {
source: "avatar.png"
width: 40; height: 40
fillMode: Image.PreserveAspectFit
}
Column {
Text { text: "姓名:张三"
}
Text { text: "电话:123456789"
}
}
}
}
}
}
2.3.4 元素 Flow 的介绍和使用

  在 QML 中,Flow 是一个布局容器,它会将子元素从 左到右水平排列,当一行排满时,自动换行到下一行。适用于 标签云、图片展示、动态按钮列表等内容数量不定、宽度可能变化的场景。

基本用法:

Flow {
width: 300
spacing: 10
Rectangle { width: 80; height: 40; color: "lightblue"
}
Rectangle { width: 100; height: 40; color: "lightgreen"
}
Rectangle { width: 120; height: 40; color: "lightpink"
}
Rectangle { width: 60; height: 40; color: "orange"
}
Rectangle { width: 90; height: 40; color: "yellow"
}
}

效果说明:

  • 子项先在当前行从左到右排布
  • 若子项宽度之和超过 Flow 宽度,会自动换到下一行
  • 支持动态子项数量和大小,非常适合适配宽度变化

常用属性:
在这里插入图片描述
示例:标签自动换行展示

Flow {
width: 300
spacing: 8
Repeater {
model: ["C++", "Python", "JavaScript", "Rust", "Go", "Qt", "QML", "OpenCV"]
Rectangle {
height: 30
width: textItem.width + 20
color: "#d0e8ff"
radius: 4
Text {
id: textItem
anchors.centerIn: parent
text: modelData
font.pixelSize: 14
}
}
}
}

示例:方向从上往下排列(flow: TopToBottom)

Flow {
width: 300
height: 300
spacing: 5
flow: Flow.TopToBottom
Repeater {
model: 10
Rectangle {
width: 80; height: 40
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
}
}

示例:按钮列表(自动换行)

Flow {
width: 320
spacing: 10
Repeater {
model: 15
Button {
text: "按钮" + index
}
}
}

特点总结:
在这里插入图片描述

2.3.5 元素 StackLayout 的介绍和使用

  在 QML 中,StackLayout 是一个用于 堆叠多个子项并一次只显示一个 的布局容器。它非常适合做 页面切换、多步表单、标签页内容切换 等场景。

基本概念:

  • StackLayout 将子项叠放在一起(Z 方向),只显示当前索引对应的一个子项。
  • 通过修改其 currentIndex 属性来切换显示的子项。

最简用法示例:

import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 400
height: 300
title: "StackLayout 示例"
Column {
spacing: 10
anchors.centerIn: parent
// 页面切换按钮
Row {
spacing: 10
Button { text: "页面 1"; onClicked: stack.currentIndex = 0
}
Button { text: "页面 2"; onClicked: stack.currentIndex = 1
}
Button { text: "页面 3"; onClicked: stack.currentIndex = 2
}
}
// StackLayout 布局:只显示当前索引的项
StackLayout {
id: stack
width: 300
height: 200
Rectangle {
color: "lightblue"
anchors.fill: parent
Text { text: "第一页"; anchors.centerIn: parent
}
}
Rectangle {
color: "lightgreen"
anchors.fill: parent
Text { text: "第二页"; anchors.centerIn: parent
}
}
Rectangle {
color: "lightpink"
anchors.fill: parent
Text { text: "第三页"; anchors.centerIn: parent
}
}
}
}
}

结合 Repeater + StackLayout 实现动态内容:

property int pageCount: 5
StackLayout {
id: stack
currentIndex: 0
width: 300; height: 200
Repeater {
model: pageCount
Rectangle {
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
anchors.fill: parent
Text {
anchors.centerIn: parent
text: "页面 " + (index + 1)
font.pixelSize: 20
}
}
}
}

常用属性和信号:
在这里插入图片描述

2.3.6 元素 StackView 的介绍和使用

  在 QML 中,StackView 是一个强大的页面管理组件,它维护一个页面堆栈,支持页面的 push(进入)、pop(返回) 和 replace(替换) 操作,且带有默认的页面切换动画。

非常适合用来实现:

  • 多页面导航(如设置页、详情页)
  • 向前/向后导航操作
  • 嵌套导航结构

基本结构示例:

import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 400
height: 300
title: "StackView 示例"
StackView {
id: stackView
anchors.fill: parent
initialItem: Page1 {
}
}
}

示例页面 Page1.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
Item {
width: 400; height: 300
Column {
anchors.centerIn: parent
spacing: 10
Text { text: "这是第一页"
}
Button {
text: "跳转到第二页"
onClicked: stackView.push(Qt.resolvedUrl("Page2.qml"))
}
}
}

示例页面 Page2.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
Item {
width: 400; height: 300
Column {
anchors.centerIn: parent
spacing: 10
Text { text: "这是第二页"
}
Button {
text: "返回上一页"
onClicked: stackView.pop()
}
}
}

常用操作:
在这里插入图片描述
属性与信号:
在这里插入图片描述
与 StackLayout 对比:
在这里插入图片描述

posted @ 2025-08-07 16:58  yfceshi  阅读(9)  评论(0)    收藏  举报