Qt Quick 常用控件入门:Window、Control、Button、CheckBox 与 RadioButton
2. 本节学习目标
本节主要学习以下内容:
Window和ApplicationWindow的作用区别- Qt Quick 控件的基本继承关系
Control在控件体系中的作用Button的常用属性、信号和自定义样式CheckBox的状态处理和样式自定义RadioButton的使用场景和样式自定义- Qt Quick 默认控件为什么在真实项目中经常需要重写样式
3. Qt Quick 控件的整体关系
在 Qt Quick 中,很多常用控件都来自QtQuick.Controls模块。
从继承关系上可以简单理解为:
QObject -> Item -> Control -> AbstractButton -> Button -> CheckBox -> RadioButton这里有几个关键点:
QObject是 Qt 对象体系的基础。Item是 QML 可视化对象的基础类型。Control是 Qt Quick Controls 中多数控件的基类。AbstractButton是按钮类控件的抽象基类。Button、CheckBox、RadioButton都属于按钮体系。
补充理解:
QML 和 QWidget 都属于 Qt 技术体系,但它们是两套不同的 UI 开发方式。QWidget 更偏传统桌面软件开发,而 QML 更偏声明式界面开发,常用于移动端、嵌入式、车载 HMI 和动态 UI 场景。
4. Window:Qt Quick 的顶级窗口
4.1 Window 是什么
Window是 Qt Quick 中用于创建顶级窗口的类型。一个 QML 程序想要显示出来,通常需要一个窗口作为最外层承载对象。
可以把Window理解成整个 QML 界面的外壳。
示例代码:
import QtQuick Window { width: 1024 height: 600 visible: true title: "Qt Quick Demo" }常用属性:
width:窗口宽度height:窗口高度visible:是否显示窗口title:窗口标题flags:窗口标志位,比如是否显示标题栏
初学者最容易忘的是:
visible: true如果没有设置visible: true,程序可能已经运行了,但是窗口不会显示出来。
4.2 无标题栏窗口
在桌面应用中,窗口默认会有标题栏。但在嵌入式、车载 HMI、触摸屏项目中,界面通常是全屏或无边框的。
常见写法:
import QtQuick Window { width: 1024 height: 600 visible: true flags: Qt.FramelessWindowHint }Qt.FramelessWindowHint表示创建无边框窗口。
在车载 HMI 项目中,如果整个屏幕都由 QML 界面接管,就经常会使用无标题栏窗口。
4.3 closing 信号
当窗口关闭时,会触发closing信号。可以在这个信号中做退出前处理,比如保存数据、记录日志、释放资源等。
示例:
import QtQuick Window { width: 1024 height: 600 visible: true onClosing: function(close) { console.log("window is closing") } }在普通桌面程序里,onClosing比较常见;在车载 HMI 中,窗口本身通常不会频繁关闭,更多是页面切换和状态切换。
5. ApplicationWindow:更完整的应用窗口
ApplicationWindow是Window的子类,它在Window的基础上增加了更完整的应用窗口结构。
它常见的能力包括:
menuBarheaderfooter
使用ApplicationWindow时需要导入:
import QtQuick.Controls示例代码:
import QtQuick import QtQuick.Controls ApplicationWindow { width: 1024 height: 600 visible: true title: "Application Window Demo" header: ToolBar { Label { text: "Header" anchors.centerIn: parent } } footer: ToolBar { Label { text: "Footer" anchors.centerIn: parent } } }ApplicationWindow更适合带菜单栏、工具栏、状态栏的桌面应用结构。
不过在移动端、嵌入式、车载 HMI 项目中,很多时候不会直接使用传统桌面式结构,而是自己用Window + Item + Loader + 自定义组件搭建页面系统。
6. Control:Qt Quick 控件的基类型
6.1 Control 的作用
Control是 Qt Quick Controls 中很多控件的基类。
一般情况下,我们不会直接这样写:
Control { }因为Control本身更像一个控件基础框架。它提供了一些通用能力,比如内容区域、背景、内边距等,但具体可见效果通常由子类控件实现。
实际开发中更常用的是:
Button {} CheckBox {} RadioButton {} Label {} TextField {}6.2 contentItem、background、padding、inset
理解Control,重点要理解几个概念。
contentItem表示控件内容区域。比如按钮中的文字、复选框旁边的文本,都可以通过contentItem自定义。
background表示控件背景。比如按钮的矩形底色、圆角、图片背景等。
padding表示内容区域和控件边界之间的内边距,常见属性包括:
topPaddingbottomPaddingleftPaddingrightPadding
inset表示背景和控件边界之间的偏移,常见属性包括:
topInsetbottomInsetleftInsetrightInset
这部分对自定义样式非常重要。
很多时候控件看起来“不居中”“文字贴边”“图标和文字间距不对”,本质上都是contentItem、background、padding没处理好。
7. Button:最常用的按钮控件
7.1 Button 是什么
Button是 UI 开发中最常用的控件之一,用于响应点击、按下、释放、长按等操作。
简单示例:
import QtQuick import QtQuick.Controls Button { text: "确定" onClicked: { console.log("button clicked") } }Button继承自AbstractButton,所以很多按钮相关属性和信号其实来自AbstractButton。
7.2 Button 常用属性
常用属性包括:
width:按钮宽度height:按钮高度enabled:是否可用text:按钮显示文本down:按钮是否处于按下状态autoRepeat:是否开启长按重复触发autoRepeatInterval:长按重复触发间隔
示例:
Button { width: 160 height: 48 text: "长按测试" autoRepeat: true autoRepeatInterval: 200 onClicked: { console.log("clicked") } }enabled很常用。当设置为false时,按钮不可点击,也不会响应点击事件。
Button { text: "不可点击" enabled: false }7.3 Button 常用信号
按钮常见信号包括:
pressedreleasedclickeddoubleClickedpressAndHoldtoggled
示例:
Button { text: "按钮" onPressed: { console.log("pressed") } onReleased: { console.log("released") } onClicked: { console.log("clicked") } onPressAndHold: { console.log("press and hold") } }一般情况下,信号触发顺序可以理解为:
pressed -> released -> clicked如果是长按,则中间可能触发:
pressed -> pressAndHold -> released -> clicked在桌面平台中,双击比较常见,比如双击打开应用;但在嵌入式触摸屏、车载 HMI 中,通常不建议依赖双击,因为触摸屏上的双击体验不稳定,也不利于安全交互。
7.4 自定义 Button 样式
真实项目中,很少直接使用默认按钮样式。尤其是车载 HMI,按钮通常来自 UI 设计稿,需要自己定义背景、圆角、图片、文字样式和状态变化。
一个简单的圆角按钮示例:
Button { id: root width: 180 height: 56 text: "播放" background: Rectangle { radius: 8 color: root.down ? "#2E7D32" : "#43A047" } contentItem: Text { text: root.text color: "white" font.pixelSize: 20 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } }这个例子中:
background控制按钮背景。contentItem控制按钮文字。root.down判断按钮是否处于按下状态。
7.5 播放/暂停按钮状态切换
课程中提到了一个播放器按钮示例:点击按钮后,在播放和暂停之间切换,并显示不同图片。
可以用一个布尔属性保存状态:
Button { id: playButton width: 80 height: 80 property bool playing: false background: Image { anchors.fill: parent source: playButton.playing ? "pause.png" : "play.png" fillMode: Image.PreserveAspectFit } contentItem: Item {} onClicked: { playing = !playing } }这个例子的核心思想是:
状态变化 -> 属性变化 -> 图片变化 -> UI 自动刷新这也是 QML 很重要的写法。不要总想着手动刷新界面,而是让界面绑定到状态。
8. CheckBox:复选框控件
8.1 CheckBox 是什么
CheckBox是复选框,用于表示选中或未选中。
常见场景:
- 设置页中开启或关闭某个功能
- 多选配置项
- 协议勾选
- 车辆功能开关
简单示例:
import QtQuick import QtQuick.Controls CheckBox { text: "开启自动大灯" onCheckedChanged: { console.log("checked:", checked) } }8.2 checked 与 checkState
CheckBox常用两个状态相关属性:
checked:是否选中,布尔值checkState:更完整的枚举状态
checkState通常有三种状态:
Qt.UncheckedQt.PartiallyCheckedQt.Checked
普通项目里最常用的是选中和未选中,也就是二态复选框。
示例:
CheckBox { text: "自动连接" checked: true onCheckedChanged: { console.log("auto connect:", checked) } }如果只是关心选中状态变化,优先使用:
onCheckedChanged8.3 自定义 CheckBox 样式
课程重点强调了CheckBox自定义样式的必要性。
Qt Quick 自带的CheckBox样式依赖平台,视觉效果比较基础。真实产品中,UI 设计师通常会给出明确的选中图标、未选中图标、禁用状态和文字颜色要求。
在 QML 中,常用indicator自定义复选框前面的勾选区域。
示例:
CheckBox { id: checkBox text: "记住选择" indicator: Rectangle { width: 24 height: 24 radius: 4 border.width: 2 border.color: checkBox.checked ? "#1E88E5" : "#999999" color: checkBox.checked ? "#1E88E5" : "transparent" Text { anchors.centerIn: parent text: checkBox.checked ? "✓" : "" color: "white" font.pixelSize: 18 } } contentItem: Text { text: checkBox.text color: checkBox.enabled ? "white" : "#777777" font.pixelSize: 20 leftPadding: checkBox.indicator.width + 12 verticalAlignment: Text.AlignVCenter } }这个例子中:
indicator控制左侧复选框图标。contentItem控制右侧文字。checked决定选中样式。enabled决定禁用样式。
如果项目里有图片资源,也可以用Image替代Rectangle。
9. RadioButton:单选框控件
9.1 RadioButton 是什么
RadioButton是单选按钮。它和CheckBox很像,但使用场景不同。
CheckBox适合多选:
可同时选择 A、B、CRadioButton适合单选:
只能在 A、B、C 中选一个常见场景:
- 语言选择
- 主题选择
- 驾驶模式选择
- 单位选择,比如 km/h 或 mph
示例:
Column { RadioButton { text: "中文" checked: true } RadioButton { text: "English" } RadioButton { text: "Deutsch" } }同一个父级下的多个RadioButton通常会表现出互斥选择效果。如果项目结构复杂,也可以配合ButtonGroup明确管理一组单选按钮。
9.2 RadioButton 常用属性与信号
RadioButton也继承自AbstractButton,所以常用属性和CheckBox类似:
widthheightenabledtextcheckedcheckState
状态变化时可以这样处理:
RadioButton { text: "中文" onCheckedChanged: { if (checked) { console.log("language: zh_CN") } } }注意:
单选按钮一般只关心“被选中”的时刻,所以常见写法是:
if (checked) { // 执行选中后的逻辑 }否则取消选中时也会触发一次状态变化,容易误处理。
9.3 自定义 RadioButton 样式
RadioButton的自定义思路和CheckBox类似,也是重点改indicator和contentItem。
示例:
RadioButton { id: radio text: "舒适模式" indicator: Rectangle { width: 24 height: 24 radius: 12 border.width: 2 border.color: radio.checked ? "#00C853" : "#999999" color: "transparent" Rectangle { width: 12 height: 12 radius: 6 anchors.centerIn: parent visible: radio.checked color: "#00C853" } } contentItem: Text { text: radio.text color: radio.enabled ? "white" : "#777777" font.pixelSize: 20 leftPadding: radio.indicator.width + 12 verticalAlignment: Text.AlignVCenter } }这里用两个圆形Rectangle组成单选框:
- 外层圆表示按钮边框。
- 内层圆表示选中状态。
visible: radio.checked控制内层圆是否显示。
10. 常见问题与踩坑
问题 1:Window 写了但窗口不显示
现象:
程序运行了,但是看不到窗口。
原因:
可能忘记写:
visible: true解决:
Window { width: 1024 height: 600 visible: true }复习时记住:
Window是顶级窗口,但默认不一定显示,初学时先检查visible。
问题 2:默认控件样式不好看
现象:
Button、CheckBox、RadioButton默认样式和设计稿差距很大。
原因:
Qt Quick Controls 的默认样式偏通用,不一定适合车载 HMI 或产品级界面。
解决:
根据控件类型自定义:
Button:重点改background和contentItemCheckBox:重点改indicator和contentItemRadioButton:重点改indicator和contentItem
复习时记住:
真实项目里,控件默认样式通常只是功能验证用,最终大多要按 UI 设计稿重写。
问题 3:Button 的 clicked、pressed、released 分不清
现象:
不知道应该把逻辑写在onClicked、onPressed还是onReleased。
原因:
这些信号关注的时机不同。
解决:
- 点击完成后执行逻辑:用
onClicked - 按下瞬间改变视觉状态:用
onPressed或绑定down - 松手时处理:用
onReleased - 长按逻辑:用
onPressAndHold或autoRepeat
复习时记住:
大多数普通按钮业务逻辑写在onClicked就够了。
问题 4:CheckBox 和 RadioButton 不知道怎么选
现象:
设置页里不知道该用复选框还是单选框。
原因:
两者都是按钮体系控件,但选择语义不同。
解决:
- 可以同时选择多个:用
CheckBox - 一组选项只能选一个:用
RadioButton
示例:
是否开启自动大灯:CheckBox 语言选择:RadioButton11. 小结
这节课的主线很清楚:
先从顶层窗口Window讲起,再介绍更完整的ApplicationWindow,然后进入 Qt Quick Controls 的基础类型Control,最后讲三个最常用的按钮体系控件:Button、CheckBox、RadioButton。
需要重点掌握的是:
Window是顶级窗口,初学时记得设置visible: true。ApplicationWindow更偏桌面应用窗口结构。Control是很多控件的基类,理解它有助于理解自定义样式。Button是最常用控件,重点掌握属性、信号和样式重写。CheckBox用于多选或开关类选项。RadioButton用于一组选项中的单选。- 真实产品开发中,默认控件样式通常无法满足需求,自定义样式是重点。
对车载 HMI 或嵌入式界面开发来说,最重要的不是“会拖一个按钮出来”,而是能把按钮、状态、图片、文字、禁用态、选中态、按下态都封装成稳定可复用的组件。
12. 复习清单
Window的作用是什么?- 为什么
Window经常要写visible: true? ApplicationWindow比Window多了哪些结构?- 为什么 Qt Quick 更偏移动端、嵌入式和 HMI?
Control、Item、QObject之间大概是什么继承关系?contentItem和background分别负责什么?padding和inset有什么区别?Button常用属性有哪些?pressed、released、clicked的触发关系是什么?autoRepeat适合什么场景?- 如何自定义一个 Button 的背景和文字?
CheckBox的checked和checkState有什么区别?CheckBox的indicator通常用来改什么?RadioButton和CheckBox的使用场景区别是什么?- 为什么真实项目里经常不用默认控件样式?
- 如果要做车载 HMI 设置页,哪些控件适合封装成自定义组件?