Qt Quick 常用控件入门:Window、Button、CheckBox 与 RadioButton

Qt Quick 常用控件入门:Window、Control、Button、CheckBox 与 RadioButton

2. 本节学习目标

本节主要学习以下内容:

  • WindowApplicationWindow 的作用区别
  • Qt Quick 控件的基本继承关系
  • Control 在控件体系中的作用
  • Button 的常用属性、信号和自定义样式
  • CheckBox 的状态处理和样式自定义
  • RadioButton 的使用场景和样式自定义
  • Qt Quick 默认控件为什么在真实项目中经常需要重写样式

3. Qt Quick 控件的整体关系

在 Qt Quick 中,很多常用控件都来自 QtQuick.Controls 模块。

从继承关系上可以简单理解为:

text 复制代码
QObject
  -> Item
      -> Control
          -> AbstractButton
              -> Button
              -> CheckBox
              -> RadioButton

这里有几个关键点:

  • QObject 是 Qt 对象体系的基础。
  • Item 是 QML 可视化对象的基础类型。
  • Control 是 Qt Quick Controls 中多数控件的基类。
  • AbstractButton 是按钮类控件的抽象基类。
  • ButtonCheckBoxRadioButton 都属于按钮体系。

补充理解:

QML 和 QWidget 都属于 Qt 技术体系,但它们是两套不同的 UI 开发方式。QWidget 更偏传统桌面软件开发,而 QML 更偏声明式界面开发,常用于移动端、嵌入式、车载 HMI 和动态 UI 场景。

4. Window:Qt Quick 的顶级窗口

4.1 Window 是什么

Window 是 Qt Quick 中用于创建顶级窗口的类型。一个 QML 程序想要显示出来,通常需要一个窗口作为最外层承载对象。

可以把 Window 理解成整个 QML 界面的外壳。

示例代码:

qml 复制代码
import QtQuick

Window {
    width: 1024
    height: 600
    visible: true
    title: "Qt Quick Demo"
}

常用属性:

  • width:窗口宽度
  • height:窗口高度
  • visible:是否显示窗口
  • title:窗口标题
  • flags:窗口标志位,比如是否显示标题栏

初学者最容易忘的是:

qml 复制代码
visible: true

如果没有设置 visible: true,程序可能已经运行了,但是窗口不会显示出来。

4.2 无标题栏窗口

在桌面应用中,窗口默认会有标题栏。但在嵌入式、车载 HMI、触摸屏项目中,界面通常是全屏或无边框的。

常见写法:

qml 复制代码
import QtQuick

Window {
    width: 1024
    height: 600
    visible: true
    flags: Qt.FramelessWindowHint
}

Qt.FramelessWindowHint 表示创建无边框窗口。

在车载 HMI 项目中,如果整个屏幕都由 QML 界面接管,就经常会使用无标题栏窗口。

4.3 closing 信号

当窗口关闭时,会触发 closing 信号。可以在这个信号中做退出前处理,比如保存数据、记录日志、释放资源等。

示例:

qml 复制代码
import QtQuick

Window {
    width: 1024
    height: 600
    visible: true

    onClosing: function(close) {
        console.log("window is closing")
    }
}

在普通桌面程序里,onClosing 比较常见;在车载 HMI 中,窗口本身通常不会频繁关闭,更多是页面切换和状态切换。

5. ApplicationWindow:更完整的应用窗口

ApplicationWindowWindow 的子类,它在 Window 的基础上增加了更完整的应用窗口结构。

它常见的能力包括:

  • menuBar
  • header
  • footer

使用 ApplicationWindow 时需要导入:

qml 复制代码
import QtQuick.Controls

示例代码:

qml 复制代码
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 中很多控件的基类。

一般情况下,我们不会直接这样写:

qml 复制代码
Control {
}

因为 Control 本身更像一个控件基础框架。它提供了一些通用能力,比如内容区域、背景、内边距等,但具体可见效果通常由子类控件实现。

实际开发中更常用的是:

qml 复制代码
Button {}
CheckBox {}
RadioButton {}
Label {}
TextField {}

6.2 contentItem、background、padding、inset

理解 Control,重点要理解几个概念。

contentItem 表示控件内容区域。比如按钮中的文字、复选框旁边的文本,都可以通过 contentItem 自定义。

background 表示控件背景。比如按钮的矩形底色、圆角、图片背景等。

padding 表示内容区域和控件边界之间的内边距,常见属性包括:

  • topPadding
  • bottomPadding
  • leftPadding
  • rightPadding

inset 表示背景和控件边界之间的偏移,常见属性包括:

  • topInset
  • bottomInset
  • leftInset
  • rightInset

这部分对自定义样式非常重要。

很多时候控件看起来"不居中""文字贴边""图标和文字间距不对",本质上都是 contentItembackgroundpadding 没处理好。

7. Button:最常用的按钮控件

7.1 Button 是什么

Button 是 UI 开发中最常用的控件之一,用于响应点击、按下、释放、长按等操作。

简单示例:

qml 复制代码
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:长按重复触发间隔

示例:

qml 复制代码
Button {
    width: 160
    height: 48
    text: "长按测试"
    autoRepeat: true
    autoRepeatInterval: 200

    onClicked: {
        console.log("clicked")
    }
}

enabled 很常用。当设置为 false 时,按钮不可点击,也不会响应点击事件。

qml 复制代码
Button {
    text: "不可点击"
    enabled: false
}

7.3 Button 常用信号

按钮常见信号包括:

  • pressed
  • released
  • clicked
  • doubleClicked
  • pressAndHold
  • toggled

示例:

qml 复制代码
Button {
    text: "按钮"

    onPressed: {
        console.log("pressed")
    }

    onReleased: {
        console.log("released")
    }

    onClicked: {
        console.log("clicked")
    }

    onPressAndHold: {
        console.log("press and hold")
    }
}

一般情况下,信号触发顺序可以理解为:

text 复制代码
pressed -> released -> clicked

如果是长按,则中间可能触发:

text 复制代码
pressed -> pressAndHold -> released -> clicked

在桌面平台中,双击比较常见,比如双击打开应用;但在嵌入式触摸屏、车载 HMI 中,通常不建议依赖双击,因为触摸屏上的双击体验不稳定,也不利于安全交互。

7.4 自定义 Button 样式

真实项目中,很少直接使用默认按钮样式。尤其是车载 HMI,按钮通常来自 UI 设计稿,需要自己定义背景、圆角、图片、文字样式和状态变化。

一个简单的圆角按钮示例:

qml 复制代码
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 播放/暂停按钮状态切换

课程中提到了一个播放器按钮示例:点击按钮后,在播放和暂停之间切换,并显示不同图片。

可以用一个布尔属性保存状态:

qml 复制代码
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
    }
}

这个例子的核心思想是:

text 复制代码
状态变化 -> 属性变化 -> 图片变化 -> UI 自动刷新

这也是 QML 很重要的写法。不要总想着手动刷新界面,而是让界面绑定到状态。

8. CheckBox:复选框控件

8.1 CheckBox 是什么

CheckBox 是复选框,用于表示选中或未选中。

常见场景:

  • 设置页中开启或关闭某个功能
  • 多选配置项
  • 协议勾选
  • 车辆功能开关

简单示例:

qml 复制代码
import QtQuick
import QtQuick.Controls

CheckBox {
    text: "开启自动大灯"

    onCheckedChanged: {
        console.log("checked:", checked)
    }
}

8.2 checked 与 checkState

CheckBox 常用两个状态相关属性:

  • checked:是否选中,布尔值
  • checkState:更完整的枚举状态

checkState 通常有三种状态:

  • Qt.Unchecked
  • Qt.PartiallyChecked
  • Qt.Checked

普通项目里最常用的是选中和未选中,也就是二态复选框。

示例:

qml 复制代码
CheckBox {
    text: "自动连接"
    checked: true

    onCheckedChanged: {
        console.log("auto connect:", checked)
    }
}

如果只是关心选中状态变化,优先使用:

qml 复制代码
onCheckedChanged

8.3 自定义 CheckBox 样式

课程重点强调了 CheckBox 自定义样式的必要性。

Qt Quick 自带的 CheckBox 样式依赖平台,视觉效果比较基础。真实产品中,UI 设计师通常会给出明确的选中图标、未选中图标、禁用状态和文字颜色要求。

在 QML 中,常用 indicator 自定义复选框前面的勾选区域。

示例:

qml 复制代码
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 适合多选:

text 复制代码
可同时选择 A、B、C

RadioButton 适合单选:

text 复制代码
只能在 A、B、C 中选一个

常见场景:

  • 语言选择
  • 主题选择
  • 驾驶模式选择
  • 单位选择,比如 km/h 或 mph

示例:

qml 复制代码
Column {
    RadioButton {
        text: "中文"
        checked: true
    }

    RadioButton {
        text: "English"
    }

    RadioButton {
        text: "Deutsch"
    }
}

同一个父级下的多个 RadioButton 通常会表现出互斥选择效果。如果项目结构复杂,也可以配合 ButtonGroup 明确管理一组单选按钮。

9.2 RadioButton 常用属性与信号

RadioButton 也继承自 AbstractButton,所以常用属性和 CheckBox 类似:

  • width
  • height
  • enabled
  • text
  • checked
  • checkState

状态变化时可以这样处理:

qml 复制代码
RadioButton {
    text: "中文"

    onCheckedChanged: {
        if (checked) {
            console.log("language: zh_CN")
        }
    }
}

注意:

单选按钮一般只关心"被选中"的时刻,所以常见写法是:

qml 复制代码
if (checked) {
    // 执行选中后的逻辑
}

否则取消选中时也会触发一次状态变化,容易误处理。

9.3 自定义 RadioButton 样式

RadioButton 的自定义思路和 CheckBox 类似,也是重点改 indicatorcontentItem

示例:

qml 复制代码
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 写了但窗口不显示

现象:

程序运行了,但是看不到窗口。

原因:

可能忘记写:

qml 复制代码
visible: true

解决:

qml 复制代码
Window {
    width: 1024
    height: 600
    visible: true
}

复习时记住:

Window 是顶级窗口,但默认不一定显示,初学时先检查 visible

问题 2:默认控件样式不好看

现象:

ButtonCheckBoxRadioButton 默认样式和设计稿差距很大。

原因:

Qt Quick Controls 的默认样式偏通用,不一定适合车载 HMI 或产品级界面。

解决:

根据控件类型自定义:

  • Button:重点改 backgroundcontentItem
  • CheckBox:重点改 indicatorcontentItem
  • RadioButton:重点改 indicatorcontentItem

复习时记住:

真实项目里,控件默认样式通常只是功能验证用,最终大多要按 UI 设计稿重写。

问题 3:Button 的 clicked、pressed、released 分不清

现象:

不知道应该把逻辑写在 onClickedonPressed 还是 onReleased

原因:

这些信号关注的时机不同。

解决:

  • 点击完成后执行逻辑:用 onClicked
  • 按下瞬间改变视觉状态:用 onPressed 或绑定 down
  • 松手时处理:用 onReleased
  • 长按逻辑:用 onPressAndHoldautoRepeat

复习时记住:

大多数普通按钮业务逻辑写在 onClicked 就够了。

问题 4:CheckBox 和 RadioButton 不知道怎么选

现象:

设置页里不知道该用复选框还是单选框。

原因:

两者都是按钮体系控件,但选择语义不同。

解决:

  • 可以同时选择多个:用 CheckBox
  • 一组选项只能选一个:用 RadioButton

示例:

text 复制代码
是否开启自动大灯:CheckBox
语言选择:RadioButton

11. 小结

这节课的主线很清楚:

先从顶层窗口 Window 讲起,再介绍更完整的 ApplicationWindow,然后进入 Qt Quick Controls 的基础类型 Control,最后讲三个最常用的按钮体系控件:ButtonCheckBoxRadioButton

需要重点掌握的是:

  • Window 是顶级窗口,初学时记得设置 visible: true
  • ApplicationWindow 更偏桌面应用窗口结构。
  • Control 是很多控件的基类,理解它有助于理解自定义样式。
  • Button 是最常用控件,重点掌握属性、信号和样式重写。
  • CheckBox 用于多选或开关类选项。
  • RadioButton 用于一组选项中的单选。
  • 真实产品开发中,默认控件样式通常无法满足需求,自定义样式是重点。

对车载 HMI 或嵌入式界面开发来说,最重要的不是"会拖一个按钮出来",而是能把按钮、状态、图片、文字、禁用态、选中态、按下态都封装成稳定可复用的组件。

12. 复习清单

  • Window 的作用是什么?
  • 为什么 Window 经常要写 visible: true
  • ApplicationWindowWindow 多了哪些结构?
  • 为什么 Qt Quick 更偏移动端、嵌入式和 HMI?
  • ControlItemQObject 之间大概是什么继承关系?
  • contentItembackground 分别负责什么?
  • paddinginset 有什么区别?
  • Button 常用属性有哪些?
  • pressedreleasedclicked 的触发关系是什么?
  • autoRepeat 适合什么场景?
  • 如何自定义一个 Button 的背景和文字?
  • CheckBoxcheckedcheckState 有什么区别?
  • CheckBoxindicator 通常用来改什么?
  • RadioButtonCheckBox 的使用场景区别是什么?
  • 为什么真实项目里经常不用默认控件样式?
  • 如果要做车载 HMI 设置页,哪些控件适合封装成自定义组件?
相关推荐
qq_4017004113 小时前
Qt QSS 完全入门写出漂亮界面以及解决样式不生效问题
开发语言·qt
旖-旎14 小时前
QT系统篇(5)(下)
开发语言·c++·qt
Irissgwe14 小时前
第四章 QT窗口
qt
郝学胜_神的一滴16 小时前
Qt 高级编程 034:深耕QWidget底层内核—彻底吃透无边框窗口设计核心原理
c++·qt
澈20717 小时前
【无标题】QT入门第十二天:数据库编程(下)模型视图与数据展示 | 零基础学QT
数据库·qt·oracle
luoyayun36120 小时前
Qt/QML音视频文件原始十六进制查看器
qt·音视频·十六进制查看
小c君tt20 小时前
QT笔记记录
开发语言·笔记·qt
澈2071 天前
QT入门第十一天:数据库编程(上)SQLite入门与增删改查 | 零基础学QT
数据库·qt·sqlite
原来是猿2 天前
Qt 信号与槽机制详解(上篇):从入门到实践
开发语言·qt