【QT第三章】常用控件1
【QT第三章】常用控件1
引言📚
在 Qt 开发中,控件(Widget)是构建图形化界面的核心要素。无论是简单的按钮、标签,还是复杂的交互组件,掌握 Qt 控件的使用方法都是打造高质量界面的基础。本文将从核心概念出发,循序渐进讲解 Qt 控件的属性、API、资源管理、样式美化及实战技巧,帮助开发者快速上手并灵活运用各类控件,解决实际开发中的界面设计与交互问题。本文基于 Qt 相关技术(参考文档未明确具体版本,以通用核心特性为准)展开讲解。
一、核心概念:Qt 控件基础认知🔧
1.1 控件的本质与分类
Qt 中的控件(Widget) 是构成 GUI 界面的基本单元,其英文原义为 “小部件”,是 Qt 中的核心概念。Qt 提供了丰富的控件库,从基础的 QPushButton、QLabel 到复杂的容器控件,覆盖了绝大多数界面开发场景。
控件体系存在明确的继承关系:QWidget 是所有控件的基类,提供了通用属性与方法;QAbstractButton 作为抽象类(包含纯虚函数,无法创建实例,需通过子类重写纯虚函数才能创建实例),衍生出 QPushButton、QRadioButton、QCheckBox、QToolButton 等按钮类控件,共享按钮相关的核心功能(如点击信号、图标设置等)。
1.2 Qt 控件的外观与优化
Qt 的默认控件在美观程度上,相比更现代的控件体系存在一定差距,Qt Designer 中展示的控件均为默认样式。不过 Qt 提供了多种优化手段提升控件颜值:
- 基础优化:通过调整控件属性、使用 QSS(Qt Style Sheet)设置样式,改善界面外观。
- 专业工具:Qt 近几年推出的 Qt Design Studio,对标现代化界面体系,能制作出业界领先水准的界面,但该工具为收费版本,日常学习场景暂不涉及。
在 Qt Creator 中,右侧面板可直接查看并编辑 QWidget 的各类属性,这些属性无需逐一掌握,重点了解常用、重要属性即可,具体可通过 Qt 官方文档深入查询。
1.3 对象树机制
Qt 通过对象树管理控件生命周期,当一个控件设置了父对象,它会被加入父对象的子对象列表。销毁父对象时,所有子对象会自动销毁,无需手动释放内存,这极大简化了内存管理。
需要注意的是,QIcon 等小型对象不支持对象树,其生命周期不依赖父对象,创建后即使释放,也不影响已设置的图标显示。之前推荐使用堆创建对象,核心原因是确保控件生命周期足够长,可通过 Qt 对象树自动释放,而 QIcon 因自身特性无需依赖此机制。
1.4 Qt 坐标系规则
Qt 中控件的位置与尺寸基于特定坐标系,不同 API 的坐标基准存在差异,这是界面布局设计的关键:
geometry()/setGeometry():以控件本体左上角为原点(不考虑窗口框架),返回 / 设置控件的 x、y 坐标(左上角)及宽高(width、height)。其中setGeometry()有两种重载形式,可直接传入 QRect 对象,或分别传入 x、y、width、height 四个整数参数。frameGeometry():以窗口框架左上角为原点,包含窗口框架的整体尺寸,返回结果同样为 QRect 对象。- 坐标单位为像素,x 轴向右为正方向,y 轴向下为正方向。
在代码实践中,若在 Widget 构造函数中直接调用
geometry()和frameGeometry(),由于此时 Widget 对象尚未加入窗口框架,无法观察到窗口框架对坐标的影响。只有当 Widget 对象完成初始化并显示后,才能准确获取包含窗口框架的尺寸信息。学习提示:区分不同 API 的坐标基准是避免界面布局错乱的关键,建议在 Widget 显示后(如通过按钮触发)打印
geometry()与frameGeometry()的结果,直观对比两者差异。1.5 控件的 objectName 属性
在 Qt 界面开发中,每个控件的
objectName必须唯一,不能重复,后续可通过ui->objectName的方式获取对应的控件对象,例如ui->pushButton获取第一个按钮对象,ui->pushButton_2获取第二个按钮对象。Qt 会根据 ui 文件自动生成
ui_widget.h文件,生成过程中会识别界面上的所有控件及各自的objectName。默认情况下,自动生成的objectName遵循 “控件类型 + 下划线 + 数字” 的规律(如pushButton_1、label_2),但这种以数字结尾的命名方式不符合良好的编程习惯,建议手动修改为具有语义的名称(如pushButton_submit、label_username),提升代码可读性与可维护性。
二、常用核心属性与 API🔨
2.1 启用状态(enabled)
enabled属性用于描述控件是否处于 “可用” 状态,与之相对的概念是 “禁用”。
- 禁用状态:控件无法接收任何用户输入事件(如点击、键盘操作),且外观通常呈灰色;若一个 Widget 被禁用,其包含的所有子元素也会自动被禁用,实现状态的层级传递。
- 核心 API:
isEnabled():获取控件当前的可用状态,返回 bool 类型,true表示可用,false表示禁用。setEnabled(bool flag):设置控件的可用状态,参数flag为true时启用控件,为false时禁用控件。2.2 几何属性(位置与尺寸)
几何属性用于精确控制控件的布局位置与大小,Qt 中通过 QPoint(表示点)和 QRect(表示矩形)两个类封装几何概念,这两个类均属于小型对象,在 C++ 中使用便捷。
- 核心 API:
QRect geometry():获取控件的位置与尺寸,返回 QRect 对象,包含 x(左上角 x 坐标)、y(左上角 y 坐标)、width(宽度)、height(高度)四个属性。setGeometry(QRect rect):通过 QRect 对象批量设置控件的位置与尺寸。setGeometry(int x, int y, int width, int height):分别传入 x、y、width、height 四个整数参数,单独设置控件的位置与尺寸。示例:通过四个方向按钮控制目标按钮(pushButton_target)移动,每次移动 5 像素
// 向上移动 void MyWidget::on_pushButton_up_clicked() {QRect rect = ui->pushButton_target->geometry();rect.setY(rect.y() - 5);ui->pushButton_target->setGeometry(rect.x(), rect.y() - 5, rect.width(), rect.height()); }// 向下移动 void MyWidget::on_pushButton_bottom_clicked() {QRect rect = ui->pushButton_target->geometry();rect.setY(rect.y() + 5);ui->pushButton_target->setGeometry(rect.x(), rect.y() + 5, rect.width(), rect.height()); }// 向左移动 void MyWidget::on_pushButton_left_clicked() {QRect rect = ui->pushButton_target->geometry();rect.setX(rect.x() - 5);ui->pushButton_target->setGeometry(rect.x() - 5, rect.y(), rect.width(), rect.height()); }// 向右移动 void MyWidget::on_pushButton_right_clicked() {QRect rect = ui->pushButton_target->geometry();rect.setX(rect.x() + 5);ui->pushButton_target->setGeometry(rect.x() + 5, rect.y(), rect.width(), rect.height()); }2.3 透明度(opacity)
opacity属性实际表示 “不透明度”,数值越大,控件越不透明,取值范围为 0.0(全透明)到 1.0(完全不透明)。
- 核心 API:
windowOpacity():获取当前控件的不透明度,返回 float 类型。setWindowOpacity(float value):设置控件的不透明度,参数value需在 0.0~1.0 范围内。在实际使用中,存在两个需要注意的问题:
- 透明度变化不精确:由于浮点数在内存中基于 IEEE 754 标准存储,部分小数(如 0.1)无法精确表示,导致透明度变化可能出现微小误差(例如实际变化值为 0.098039、0.096078 等,而非精确的 0.1)。
- 防御性编程:虽然
setWindowOpacity()内部会自动判定参数范围,超过 1.0 或低于 0.0 的值会被截断,但在代码中仍建议手动添加范围判定(如if(opacity >= 1.0) return;),避免无效计算,提升代码健壮性。示例:逐渐降低窗口透明度
void MyWidget::decreaseOpacity() {float opacity = this->windowOpacity();if (opacity <= 0.0) return; // 避免透明度低于0.0opacity -= 0.1;this->setWindowOpacity(opacity); }常见误区⚠️:切勿直接比较两个浮点数的透明度值(如
if(opacity == 0.5)),应通过判断两者差值的绝对值是否小于极小值(如if(abs(opacity1 - opacity2) < 1e-6))来判定是否相等,避免浮点数精度问题导致逻辑错误。2.4 光标(cursor)
Qt 支持多种内置光标形状,也可通过自定义图片设置光标,满足不同交互场景需求。
- 内置光标形状:Qt 提供了 20 余种内置光标,如 ArrowCursor(箭头光标)、CrossCursor(十字光标)、WaitCursor(等待光标)、PointingHandCursor(手型光标)、SizeAllCursor(四向调整光标)等,可通过
Qt::CursorShape枚举值直接调用。- 自定义光标:基于 QPixmap 图片创建,需指定光标热点(即鼠标点击的有效位置),热点坐标以图片左上角为原点(0,0)。
- 关键操作:
- 加载图片:通过 QPixmap 加载自定义光标图片,建议使用 QRC 机制管理图片资源。
- 图片缩放:若图片尺寸过大,可通过
scaled(int width, int height)函数缩放,该函数返回新的 QPixmap 对象,不修改原图片。- 设置热点:创建 QCursor 对象时,传入图片和热点坐标(如
QCursor(pixmap, 10, 10)),表示热点在图片左上角(10,10)位置。示例:设置自定义图片光标
void MyWidget::setCustomCursor() {// 加载并缩放图片(通过QRC资源)QPixmap pixmap(":/image/custom_cursor.png");pixmap = pixmap.scaled(32, 32); // 缩放到32x32像素,符合光标常规尺寸// 设置热点为图片中心(16,16)QCursor customCursor(pixmap, 16, 16);// 应用自定义光标到当前窗口this->setCursor(customCursor); }2.5 字体(font)
font属性用于控制控件中文本的显示样式,Qt 通过 QFont 类封装字体相关属性,支持字体家族、大小、粗细、倾斜等多种设置。
核心字体属性:
属性 说明 取值范围 / 示例 family 字体家族(字体名称) “微软雅黑”“楷体”“Arial” pointSize 字体大小(像素) 12、14、16(正整数) weight 字体粗细 0~99(数值越大越粗,75 为默认加粗) bold 是否加粗 bool 类型, true等价于 weight=75italic 是否倾斜(斜体) bool 类型 underline 是否添加下划线 bool 类型 strikeOut 是否添加删除线 bool 类型 核心 API:
font():获取当前控件的字体信息,返回 QFont 对象。setFont(const QFont& font):设置控件的字体信息,传入 QFont 对象。示例:设置按钮文本字体为仿宋、12 号、加粗
void MyWidget::setButtonFont() {QFont buttonFont = this->font(); // 获取当前窗口默认字体buttonFont.setFamily("仿宋"); // 设置字体家族buttonFont.setPointSize(12); // 设置字体大小buttonFont.setBold(true); // 设置加粗(等价于buttonFont.setWeight(75))// 应用字体到按钮ui->pushButton_submit->setFont(buttonFont); }2.6 提示文本(toolTip)
toolTip是控件的辅助提示功能,当鼠标悬停在控件上时,会弹出提示文本,帮助用户理解控件功能,提升界面易用性。
- 核心 API:
setToolTip(const QString& text):设置提示文本内容,支持纯文本格式。setToolTipDuration(int ms):设置提示文本的显示时长,单位为毫秒(ms),超过时长后提示自动消失;若不设置,默认根据文本长度自动调整显示时间。示例:为提交按钮设置提示文本,显示 5 秒后消失
void MyWidget::setButtonToolTip() {// 设置提示内容ui->pushButton_submit->setToolTip("点击提交表单,提交前请确认信息无误");// 设置显示时长为5000毫秒(5秒)ui->pushButton_submit->setToolTipDuration(5000); }2.7 焦点策略(focusPolicy)
focusPolicy用于设置控件获取焦点的策略,“焦点” 指控件被选中的状态,获取焦点后,后续的键盘操作(如输入、回车)会直接作用于该控件,该属性对输入框、单选框、复选框等交互控件尤为重要。
- 核心功能:控制控件是否能通过鼠标点击、Tab 键切换等方式获取焦点。例如,设置输入框支持 Tab 键获取焦点,用户可通过 Tab 键在多个输入框间快速切换,提升操作效率。
- 类比理解:类似游戏(如 War3、SC2)中 “先选中单位,再下达命令” 的逻辑,焦点就是界面中的 “被选中单位”,后续操作仅对焦点控件生效。
2.8 窗口标题与图标(windowTitle、windowIcon)
windowTitle和windowIcon是顶层窗口(如主窗口)的常用属性,仅对顶层 QWidget 有效,对按钮、标签等子控件设置无效果(不会报错,但无任何显示)。
windowTitle(窗口标题):
- 核心 API:
windowTitle()获取窗口标题,setWindowTitle(const QString& title)设置窗口标题。- 示例:
this->setWindowTitle("Qt控件演示程序");windowIcon(窗口图标):
核心 API:
windowIcon()获取窗口图标,setWindowIcon(const QIcon& icon)设置窗口图标。注意事项:QIcon 对象创建后,其生命周期不影响图标显示,且不支持对象树,无需设置父对象;建议使用 QRC 机制管理图标资源,避免路径问题。
示例:通过 QRC 资源设置窗口图标
void MyWidget::setWindowIcon() {QIcon windowIcon(":/image/app_icon.png");this->setWindowIcon(windowIcon); }
三、资源管理:QRC 机制详解🏗️
3.1 为什么需要 QRC 机制?
在 Qt 开发中,若直接使用绝对路径(如
"D:/images/rose.jpg")加载图片、图标等资源,会面临两个关键问题:
- 路径兼容性问题:目标机器的文件路径可能与开发机器不一致(如用户将图片存放在
"E:/素材/"目录),导致资源加载失败。- 资源安全性问题:外部资源文件可能被用户误删、移动或替换,导致程序运行异常。
QRC(Qt Resource Collection)机制通过将资源文件嵌入可执行文件(exe),从根本上解决上述问题。其核心原理是:Qt 在编译项目时,会根据 QRC 文件中记录的资源信息,提取资源文件的二进制数据,转换为 C++ 代码(生成
qrc_xxx.cpp文件,内含存储二进制数据的 char 数组),最终与项目其他代码一起编译到 exe 中,确保资源随程序一起分发,不依赖外部文件。3.2 QRC 机制的局限性
QRC 机制虽能解决资源路径与安全问题,但存在明显局限性:无法导入过大的资源文件(如 GB 级别的视频、大型压缩包)。此类文件若通过 QRC 嵌入 exe,会导致 exe 体积急剧增大,影响程序加载速度,因此超大文件需单独存放,并通过相对路径(而非 QRC)加载。
3.3 QRC 文件的创建与使用步骤
步骤 1:创建 QRC 文件
在 Qt Creator 中,右键点击项目名称,选择 “添加新文件”→“Qt”→“Qt Resource File”,设置文件名(如
resource.qrc),注意文件名不能包含中文和特殊符号,避免编译错误。步骤 2:添加前缀(Prefix)
QRC 文件中的 “前缀” 是一个虚拟目录,并非真实存在于本地磁盘的目录,而是 Qt 为方便资源管理抽象出来的路径标识。
- 点击 QRC 文件编辑界面中的 “添加前缀” 按钮,默认前缀为
/new/prefix1,建议修改为/(简化后续资源访问路径)。- 前缀的作用:当项目资源较多时,可通过不同前缀分类管理(如
/images/存放图片、/icons/存放图标),避免资源名称冲突。步骤 3:导入资源文件
- 将需要导入的资源文件(如图片、图标)拷贝到项目根目录,或项目根目录下的子目录(如
images/)中。必须确保资源文件与 QRC 文件在同级目录或同级目录的子目录下,否则无法导入。- 在 QRC 编辑界面中,选中已添加的前缀(如
/),点击 “添加文件” 按钮,选择需要导入的资源文件,完成导入后,QRC 文件会自动记录资源的相对路径。步骤 4:在代码中访问 QRC 资源
访问 QRC 资源的路径格式为:
":/前缀/资源文件名",其中:是 QRC 资源的固定标识,用于区分本地路径与 QRC 虚拟路径。
- 若前缀为
/,路径可简化为":/资源文件名"(如":/rose.jpg")。- 若资源存放在子目录且前缀包含子目录(如前缀为
/images/),路径为":/images/rose.jpg"。示例:通过 QRC 资源设置按钮图标
void MyWidget::setButtonIcon() {// 从QRC资源加载图标QIcon buttonIcon(":/images/button_icon.png");// 设置按钮图标ui->pushButton->setIcon(buttonIcon);// 设置图标尺寸为50x50像素ui->pushButton->setIconSize(QSize(50, 50)); }步骤 5:编译与验证
保存 QRC 文件后,编译项目,Qt 会自动生成
qrc_resource.cpp文件(存储资源二进制数据),并将其编译到 exe 中。运行程序,若资源(如图片、图标)正常显示,说明 QRC 资源加载成功。3.4 QRC 使用的注意事项
- 路径分隔符:QRC 资源路径中必须使用
/作为分隔符,不可使用\(\在 C++ 中为转义字符,会导致路径解析错误,如"d:\rose.jpg"中的\r会被解析为回车符)。若需使用本地路径,可通过 C++11 的原始字符串(raw string)解决,格式为R"(d:\rose.jpg)",但 QRC 资源无需此操作。- 资源更新:若导入的资源文件内容修改(如替换图片),需重新编译项目,确保 QRC 生成的二进制数据同步更新,否则程序仍会加载旧资源。
- 中文路径与名称:避免资源文件路径或文件名包含中文,部分编译器对中文支持不佳,可能导致资源加载失败。
学习提示:QRC 是 Qt 资源管理的最佳实践,除超大文件外,所有图片、图标、配置文件等资源均建议通过 QRC 管理,确保程序在不同机器上的兼容性与稳定性。
四、常用控件实战详解🗃️
4.1 QPushButton(按钮控件)
QPushButton 是 Qt 中最常用的交互控件,支持文本、图标、快捷键、连发等功能,广泛用于触发操作(如提交、取消、跳转)。
4.1.1 核心属性与功能
属性 说明 取值 / 示例 text 按钮上显示的文本 “提交”“取消” icon 按钮上显示的图标,通过 QIcon 设置 QIcon(“:/images/submit_icon.png”) iconSize 图标的尺寸,通过 QSize 设置,避免图标过大或过小 QSize(50, 50) shortCut 按钮的快捷键,支持单个按键(如 “A”“W”)或组合键(如 “Ctrl+S”“Alt+F4”) QKeySequence(“Ctrl+S”) autoRepeat 按住按钮时是否持续触发 clicked信号(类似游戏手柄 “连发” 功能)bool 类型, true启用连发autoRepeatDelay 连发延时:按住按钮后,延迟多久开始持续触发信号,单位为毫秒 500(延迟 500ms 开始连发) autoRepeatInterval 连发周期:持续触发信号的时间间隔,单位为毫秒 100(每 100ms 触发一次) checked 按钮是否被勾选,对普通 QPushButton 无意义,仅对复选按钮生效 bool 类型 4.1.2 常用信号
QPushButton 提供多个信号,最常用的是
clicked信号,用于响应按钮点击操作:
clicked():无参数版本,点击按钮时触发。clicked(bool checked):带参数版本,参数checked表示按钮是否被勾选,普通按钮无需使用此版本。4.1.3 实战案例:方向键控制目标按钮移动
需求:创建四个方向按钮(上、下、左、右)和一个目标按钮,通过按钮点击或快捷键控制目标按钮在窗口内移动,支持按钮连发。
实现步骤:
- 界面设计:在 Qt Designer 中拖放 5 个 QPushButton,分别命名为
pushButton_up(上)、pushButton_down(下)、pushButton_left(左)、pushButton_right(右)、pushButton_target(目标)。- 资源导入:通过 QRC 导入方向图标(up.png、down.png、left.png、right.png)和目标图标(doge.png)。
- 初始化设置:在 Widget 构造函数中设置按钮图标、图标尺寸、快捷键和连发功能。
- 编写移动逻辑:为四个方向按钮编写
clicked信号的槽函数,通过geometry()获取目标按钮位置,调整后通过setGeometry()设置新位置。核心代码:
// Widget构造函数:初始化按钮 Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 1. 设置目标按钮图标与尺寸ui->pushButton_target->setIcon(QIcon(":/image/doge.png"));ui->pushButton_target->setIconSize(QSize(120, 120));// 2. 设置方向按钮图标与尺寸ui->pushButton_up->setIcon(QIcon(":/image/up.png"));ui->pushButton_up->setIconSize(QSize(50, 50));ui->pushButton_down->setIcon(QIcon(":/image/down.png"));ui->pushButton_down->setIconSize(QSize(50, 50));ui->pushButton_left->setIcon(QIcon(":/image/left.png"));ui->pushButton_left->setIconSize(QSize(50, 50));ui->pushButton_right->setIcon(QIcon(":/image/right.png"));ui->pushButton_right->setIconSize(QSize(50, 50));// 3. 设置快捷键(W上、S下、A左、D右)ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_W));ui->pushButton_down->setShortcut(QKeySequence(Qt::Key_S));ui->pushButton_left->setShortcut(QKeySequence(Qt::Key_A));ui->pushButton_right->setShortcut(QKeySequence(Qt::Key_D));// 4. 启用按钮连发功能ui->pushButton_up->setAutoRepeat(true);ui->pushButton_down->setAutoRepeat(true);ui->pushButton_left->setAutoRepeat(true);ui->pushButton_right->setAutoRepeat(true);// 设置连发延时(500ms)和周期(100ms)ui->pushButton_up->setAutoRepeatDelay(500);ui->pushButton_up->setAutoRepeatInterval(100);// 其他方向按钮同理设置连发参数 }// 上移槽函数 void MyWidget::on_pushButton_up_clicked() {QRect rect = ui->pushButton_target->geometry();// 确保按钮上移后不超出窗口顶部if (rect.y() - 5 >= 0) {ui->pushButton_target->setGeometry(rect.x(), rect.y() - 5, rect.width(), rect.height());} }// 下移槽函数 void MyWidget::on_pushButton_down_clicked() {QRect rect = ui->pushButton_target->geometry();// 确保按钮下移后不超出窗口底部(窗口高度 - 按钮高度)if (rect.y() + 5 + rect.height() <= this->height()) {ui->pushButton_target->setGeometry(rect.x(), rect.y() + 5, rect.width(), rect.height());} }// 左移槽函数 void MyWidget::on_pushButton_left_clicked() {QRect rect = ui->pushButton_target->geometry();// 确保按钮左移后不超出窗口左侧if (rect.x() - 5 >= 0) {ui->pushButton_target->setGeometry(rect.x() - 5, rect.y(), rect.width(), rect.height());} }// 右移槽函数 void MyWidget::on_pushButton_right_clicked() {QRect rect = ui->pushButton_target->geometry();// 确保按钮右移后不超出窗口右侧(窗口宽度 - 按钮宽度)if (rect.x() + 5 + rect.width() <= this->width()) {ui->pushButton_target->setGeometry(rect.x() + 5, rect.y(), rect.width(), rect.height());} }4.2 QRadioButton(单选按钮)
QRadioButton 用于 “多选一” 场景(如选择性别、支付方式),默认情况下,同一父控件下的所有 QRadioButton 互斥(只能选中一个),若需多组单选按钮独立互斥,需使用
QButtonGroup进行分组。4.2.1 核心信号
QRadioButton 提供多个信号,用于响应状态变化:
clicked(bool checked):点击按钮时触发,参数checked表示按钮是否被选中(true为选中,false为未选中)。pressed():按下按钮时触发,无论当前状态是否变化。released():释放按钮时触发,无论当前状态是否变化。toggled(bool checked):按钮状态(选中 / 未选中)变化时触发,参数checked为变化后的状态,是最常用的状态监测信号。示例:监测单选按钮状态变化
// clicked信号槽函数 void MyWidget::on_radioButton_clicked(bool checked) {qDebug() << "单选按钮1被点击,当前状态:" << checked; }// pressed信号槽函数 void MyWidget::on_radioButton_2_pressed() {qDebug() << "单选按钮2被按下"; }// released信号槽函数 void MyWidget::on_radioButton_3_released() {qDebug() << "单选按钮3被释放"; }// toggled信号槽函数(最常用) void MyWidget::on_radioButton_4_toggled(bool checked) {qDebug() << "单选按钮4状态变化,新状态:" << checked; }4.2.2 QButtonGroup 分组功能
当界面存在多组单选按钮时(如 “汉堡选择”“小食选择”“饮料选择”),需通过
QButtonGroup将每组按钮独立分组,确保组内互斥、组间不影响。实战案例:模拟麦当劳套餐点餐(三组单选按钮)
需求:套餐包含汉堡、小食、饮料三类选项,每类只能选一个,通过 QButtonGroup 实现分组。
实现步骤:
- 界面设计:拖放 6 个 QRadioButton,分别为汉堡组(巨无霸、麦辣鸡腿堡、培根蔬萃双层牛堡)、小食组(中薯条、辣鸡翅、麦乐鸡块)、饮料组(可乐、雪碧)。
- 创建 QButtonGroup:在代码中创建三个 QButtonGroup 对象,分别对应三组单选按钮。
- 添加按钮到分组:通过
addButton(QAbstractButton* button)将单选按钮添加到对应分组。- 获取选中结果:通过
QButtonGroup::checkedButton()获取每组选中的按钮,进而获取选中文本。核心代码:
// Widget构造函数:创建分组并添加按钮 Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 1. 创建三个按钮组,父对象设为this,确保自动释放QButtonGroup* burgerGroup = new QButtonGroup(this); // 汉堡组QButtonGroup* snackGroup = new QButtonGroup(this); // 小食组QButtonGroup* drinkGroup = new QButtonGroup(this); // 饮料组// 2. 为汉堡组添加按钮burgerGroup->addButton(ui->radioButton_bigMac); // 巨无霸burgerGroup->addButton(ui->radioButton_spicyChicken); // 麦辣鸡腿堡burgerGroup->addButton(ui->radioButton_baconBurger); // 培根蔬萃双层牛堡// 3. 为小食组添加按钮snackGroup->addButton(ui->radioButton_fries); // 中薯条snackGroup->addButton(ui->radioButton_wings); // 辣鸡翅snackGroup->addButton(ui->radioButton_nuggets); // 麦乐鸡块// 4. 为饮料组添加按钮drinkGroup->addButton(ui->radioButton_coke); // 可乐drinkGroup->addButton(ui->radioButton_sprite); // 雪碧 }// 提交订单按钮槽函数:获取选中结果 void MyWidget::on_pushButton_submit_clicked() {// 获取汉堡组选中按钮QRadioButton* selectedBurger = qobject_cast<QRadioButton*>(burgerGroup->checkedButton());// 获取小食组选中按钮QRadioButton* selectedSnack = qobject_cast<QRadioButton*>(snackGroup->checkedButton());// 获取饮料组选中按钮QRadioButton* selectedDrink = qobject_cast<QRadioButton*>(drinkGroup->checkedButton());// 显示选中结果QString order = "您的订单:\n";if (selectedBurger) order += "汉堡:" + selectedBurger->text() + "\n";if (selectedSnack) order += "小食:" + selectedSnack->text() + "\n";if (selectedDrink) order += "饮料:" + selectedDrink->text() + "\n";QMessageBox::information(this, "订单确认", order); }4.3 QCheckBox(复选框)
QCheckBox 用于 “多选多” 场景(如选择兴趣爱好、勾选协议),每个复选框独立存在,可同时选中多个,核心信号为
stateChanged(int state),参数state表示复选框的状态:
Qt::Unchecked(0):未选中。Qt::PartiallyChecked(1):半选中(仅用于包含子复选框的父复选框,如树形结构中的父节点)。Qt::Checked(2):选中。示例:监测复选框状态变化
void MyWidget::on_checkBox_hobby_1_stateChanged(int state) {switch (state) {case Qt::Unchecked:qDebug() << "兴趣1:未选中";break;case Qt::Checked:qDebug() << "兴趣1:选中";break;case Qt::PartiallyChecked:qDebug() << "兴趣1:半选中(极少用)";break;default:break;} }4.4 QLabel(标签控件)
QLabel 是 Qt 中用于显示文本、图片或富文本的控件,功能灵活,不支持用户交互,主要用于信息展示(如标题、提示、图片显示)。
4.4.1 核心属性
属性 说明 取值 / 示例 textFormat 文本格式,控制文本是否解析标签 Qt::PlainText(纯文本)、Qt::RichText(富文本)、Qt::MarkdownText(Markdown 格式)、Qt::AutoText(自动判定) pixmap 标签显示的图片,通过 QPixmap 设置 QPixmap(“:/image/logo.png”) scaledContents 图片是否自动拉伸填充标签, true拉伸,false保持原尺寸bool 类型 alignment 文本或图片在标签内的对齐方式,支持水平(左、中、右)和垂直(上、中、下)组合 Qt::AlignHCenter Qt::AlignVCenter(水平垂直居中) wordWrap 文本是否自动换行, true自动换行,false超出标签宽度后隐藏bool 类型 indent 文本缩进,水平和垂直方向均生效,具体方向取决于 alignment属性50(缩进 50 像素) margin 文本 / 图片与标签边框之间的边距,上下左右四个方向同时生效 10(边距 10 像素) openExternalLinks 文本包含 URL 时,是否允许点击打开外部链接(需配合 RichText 格式) bool 类型 buddy 标签关联的 “伙伴控件”,点击标签时激活伙伴控件(如输入框、单选按钮) ui->lineEdit_username(关联用户名输入框) 4.4.2 文本格式详解
QLabel 支持四种文本格式,不同格式对标签的解析方式不同,需根据需求选择:
Qt::PlainText(纯文本):不解析任何标签,所有字符均视为普通文本。例如,
<b>加粗文本</b>会直接显示为 “<b>加粗文本</b>”,而非加粗效果。Qt::RichText(富文本):支持 HTML 标签,可实现文本加粗、倾斜、下划线、颜色、字体大小等格式化效果,类似网页中的文本样式。
示例:显示加粗、红色的富文本
ui->label_richText->setText("<b><font color='red'>这是加粗的红色富文本</font></b>"); ui->label_richText->setTextFormat(Qt::RichText);Qt::MarkdownText(Markdown 格式):支持 Markdown 语法
示例:显示 Markdown 格式文本
ui->label_markdown->setText("# 一级标题\n**加粗文本**\n*倾斜文本*"); ui->label_markdown->setTextFormat(Qt::MarkdownText);Qt::AutoText(自动判定):Qt 自动根据文本内容判定格式,若包含 HTML 标签则按 RichText 解析,若包含 Markdown 语法则按 MarkdownText 解析,否则按 PlainText 解析。
常见误区⚠️:若需显示格式化文本(如加粗、颜色),必须将
textFormat设置为Qt::RichText或Qt::MarkdownText,仅设置文本内容而不修改格式,标签无法生效。4.4.3 图片显示与自适应
QLabel 可通过
pixmap属性显示图片,配合scaledContents属性实现图片自适应标签尺寸:
示例:显示图片并自适应标签
void MyWidget::setLabelImage() {// 加载图片(QRC资源)QPixmap image(":/image/banner.png");// 设置图片到标签ui->label_image->setPixmap(image);// 启用图片自动拉伸,填充标签ui->label_image->setScaledContents(true);// 设置标签对齐方式(图片居中)ui->label_image->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); }4.4.4 标签自适应窗口大小
默认情况下,在 Widget 构造函数中通过
setGeometry()设置的 QLabel 尺寸是 “一次性” 的,窗口缩放时标签尺寸不会自动变化。若需标签尺寸跟随窗口变化,需重写 Widget 的resizeEvent事件(窗口大小变化时触发的事件)。示例:标签自适应窗口大小
// 重写resizeEvent事件 void MyWidget::resizeEvent(QResizeEvent *event) {// 调用父类事件处理,确保其他功能正常QWidget::resizeEvent(event);// 设置标签尺寸与窗口尺寸一致(x=0, y=0, 宽度=窗口宽度, 高度=窗口高度)ui->label_adapt->setGeometry(0, 0, event->size().width(), event->size().height()); }4.4.5 伙伴关系(buddy)
QLabel 的
buddy属性可关联其他控件(如输入框、单选按钮),点击标签时会自动激活伙伴控件(如将光标定位到输入框),配合快捷键使用可提升操作效率。设置伙伴关系的步骤:
- 在标签文本中,通过
&符号指定快捷键(如&Username:,表示 Alt+U 为快捷键)。- 通过
setBuddy(QWidget* widget)关联伙伴控件。示例:标签关联用户名输入框
void MyWidget::setLabelBuddy() {// 标签文本:&Username(Alt+U为快捷键)ui->label_username->setText("&Username:");// 关联伙伴控件为用户名输入框ui->label_username->setBuddy(ui->lineEdit_username);// 点击标签或按Alt+U,光标会自动定位到lineEdit_username }
五、样式美化:QSS 入门与实战🔗
Qt Style Sheet(QSS)是 Qt 借鉴 CSS(层叠样式表)推出的样式美化技术,用于自定义控件的外观,支持通过 UI 界面或代码两种方式设置,可快速实现界面主题切换、控件样式定制等效果。
5.1 QSS 与 CSS 的关系
QSS 语法与 CSS 高度兼容,但功能上存在一定差距(QSS 不支持 CSS3 的部分高级特性,如动画、渐变等),不过足以满足大多数桌面应用的美化需求。QSS 的核心思想是 “选择器 + 样式属性”,通过选择器定位控件,通过样式属性设置外观。
5.2 QSS 的两种设置方式
方式 1:通过 Qt Designer 设置(UI 方式)
- 在 Qt Designer 中,选中需要设置样式的控件(如窗口、按钮、输入框)。
- 在右侧 “属性编辑器” 中找到
styleSheet属性,点击右侧的 “…” 按钮,打开 “编辑样式表” 对话框。- 在对话框中输入 QSS 代码,实时预览效果,确认后点击 “确定”。
方式 2:通过代码设置
在 C++ 代码中,通过
setStyleSheet(const QString& styleSheet)函数设置 QSS 样式,支持为单个控件、父控件(及其子控件)或整个窗口设置样式。5.3 常用 QSS 选择器
QSS 支持多种选择器,用于定位不同范围的控件,常用选择器如下:
选择器类型 语法示例 说明 控件类型选择器 QPushButton 匹配所有 QPushButton 及其子类控件 对象名选择器 #pushButton_submit 匹配 objectName为 pushButton_submit 的控件类选择器 .MyCustomWidget 匹配所有继承自 MyCustomWidget 的控件 后代选择器 QWidget QPushButton 匹配 QWidget 下所有的 QPushButton 控件 属性选择器 QPushButton:checked 匹配所有处于选中状态的 QPushButton 5.4 QSS 实战:明暗主题切换
需求:创建两个按钮(亮色主题、暗色主题),点击按钮切换整个窗口及控件的样式,实现明暗主题切换。
核心代码:
// 亮色主题(白底黑字) void MyWidget::on_pushButton_light_clicked() {// 1. 设置窗口背景this->setStyleSheet("background-color: rgb(240, 240, 240);");// 2. 设置文本输入框样式(白色背景,黑色文本)ui->textEdit->setStyleSheet("background-color: white; color: black; border: 1px solid #CCCCCC;");// 3. 设置按钮样式(白色背景,黑色文本,灰色边框)ui->pushButton_light->setStyleSheet("background-color: white; color: black; border: 1px solid #CCCCCC;");ui->pushButton_night->setStyleSheet("background-color: white; color: black; border: 1px solid #CCCCCC;"); }// 暗色主题(黑底白字) void MyWidget::on_pushButton_night_clicked() {// 1. 设置窗口背景this->setStyleSheet("background-color: black;");// 2. 设置文本输入框样式(黑色背景,白色文本)ui->textEdit->setStyleSheet("background-color: black; color: white; border: 1px solid #666666;");// 3. 设置按钮样式(黑色背景,浅灰色文本,深灰色边框)ui->pushButton_light->setStyleSheet("background-color: black; color: rgb(240, 240, 240); border: 1px solid #666666;");ui->pushButton_night->setStyleSheet("background-color: black; color: rgb(240, 240, 240); border: 1px solid #666666;"); }学习提示:QSS 样式支持批量设置,例如通过
this->setStyleSheet("QPushButton { background-color: white; }")可一次性设置窗口内所有 QPushButton 的背景色,减少重复代码。
六、Qt 事件机制基础🧸
在 Qt 中,用户操作(如点击、窗口缩放、键盘输入)会触发两类核心概念:信号(Signal) 和事件(Event)。信号用于控件间的交互(如按钮点击触发槽函数),而事件用于处理更底层的用户操作或系统通知(如窗口缩放、鼠标移动)。
6.1 事件的特点
- 连续性:部分事件会连续触发,例如窗口缩放(
resizeEvent)时,拖动窗口边缘的过程中会持续触发resizeEvent事件。- 重写机制:Qt 中的事件通过虚函数实现,可通过重写父类的事件虚函数,自定义事件处理逻辑(如重写
resizeEvent实现控件自适应)。- 多态性:由于事件函数是虚函数,调用父类指针的事件函数时,会实际执行子类重写后的函数(多态特性)。
6.2 常用事件与重写示例
Qt 提供多种事件,常用事件包括
resizeEvent(窗口缩放)、mousePressEvent(鼠标按下)、keyPressEvent(键盘按下)等,重写事件的步骤如下:
- 在子类(如 MyWidget)中声明重写的事件函数(需加
override关键字,确保重写正确)。- 实现事件函数,编写自定义处理逻辑,同时调用父类的事件函数(如
QWidget::resizeEvent(event)),确保父类的事件处理正常执行。示例:重写
resizeEvent事件,实现标签自适应窗口// 1. 在MyWidget.h中声明重写的事件函数 class MyWidget : public QWidget {Q_OBJECT public:explicit MyWidget(QWidget *parent = nullptr);~MyWidget() override; protected:// 声明重写resizeEvent事件void resizeEvent(QResizeEvent *event) override; private:Ui::MyWidget *ui; };// 2. 在MyWidget.cpp中实现事件函数 void MyWidget::resizeEvent(QResizeEvent *event) {// 调用父类事件处理,确保窗口默认缩放功能正常QWidget::resizeEvent(event);// 自定义逻辑:标签尺寸跟随窗口变化ui->label_adapt->setGeometry(0, 0, event->size().width(), event->size().height()); }6.3 事件与信号的区别
对比维度 信号(Signal) 事件(Event) 触发场景 控件特定动作(如按钮点击、文本变化) 底层操作或系统通知(如窗口缩放、鼠标移动) 处理方式 通过信号槽连接(connect),调用槽函数 通过重写事件虚函数,自定义处理逻辑 连续性 通常单次触发(如点击按钮仅触发一次 clicked)部分事件连续触发(如 resizeEvent)使用场景 控件间交互(如按钮触发窗口关闭) 自定义控件行为(如自适应、自定义绘图)
七、核心知识点总结🎊
- 控件基础:QWidget 是所有控件的基类,对象树管理生命周期;
objectName必须唯一,建议语义化命名;坐标系需区分geometry()(不含窗口框架)与frameGeometry()(含窗口框架)。- 核心属性与 API:
- 启用状态:
enabled控制输入可用性,禁用时子控件同步禁用。- 几何属性:
geometry()/setGeometry()控制位置尺寸,QRect 封装几何信息。- 透明度:
windowOpacity()取值 0.0~1.0,注意浮点数精度问题。- 字体与提示:QFont 封装字体属性,
toolTip提升易用性。- 资源管理:QRC 机制通过嵌入资源到 exe 解决路径问题,步骤为 “创建 QRC→添加前缀→导入资源→代码访问”,超大文件需单独存放。
- 常用控件:
- QPushButton:支持图标、快捷键、连发,核心信号
clicked。- QRadioButton:多选一场景,
QButtonGroup实现分组互斥。- QLabel:支持多格式文本与图片,
resizeEvent实现自适应。- 样式美化:QSS 借鉴 CSS,通过 “选择器 + 属性” 定制样式,支持明暗主题切换。
- 事件机制:重写事件虚函数(如
resizeEvent)处理底层操作,与信号分工协作。
八、结语🚀
以上便是QT的一些常用控件的介绍与代码示例,由于篇幅有限,只介绍了部分内容,具体可以参考Qt 官方文档:Qt Documentation,进行更详细的查验。
