文章目录
前言
本文介绍QT常用控件的第三个按钮,QRadioButton 单选按钮编程。通过这个例子,初步了解QT管理资源机制,以及如何分组管理QRadioButton 单选按钮。项目演示如何使用默认的分组和 QButtonGroup 进行互斥设置,保证多个选项所在的组内只有一个被选中。项目使用样式表文件将两组按钮使用不同的样式表进行外观设置。
文章中使用的例程和内容都是在chatgpt的帮助下完成的,例程经过测试通过。
我们的调试环境仍然是双架构Kits
,编译调试在当前的ubuntu(qt5)中进行,重新编译后下载到目标arm设备(qt4)中运行。
我们的编程环境为:Ubuntu64位系统(22.04),目标架构:(1)qt5 x86_64
架构,(2)qt4 32位arm
架构。
环境配置请参见《Qt常用的按钮控件编程(一)》第1节。
感谢朋友提供的chatgpt软件,特别是其中的gpt-box桌面工具,更是我离不开的工具。感兴趣的同仁可前往一观(apsuai.com)。
5、QRadioButton 按钮
QRadioButton 是 Qt 中的一个控件类,表示一个单选按钮。在一组单选按钮中,只有一个可以被选中。通常配合 QButtonGroup 使用来实现分组单选功能。
5.1 例程功能和程序执行效果
5.1.1 例程功能
该例程利用 QRadioButton 控件实现了多选项的单选,让用户方便地进行选择。通过默认的分组和 QButtonGroup 进行互斥设置,保证多个选项所在的组内只有一个被选中,从而达到符合用户交互习惯的效果。例程中涉及到了 单选按钮(QRadioButton) 和 按钮组(QButtonGroup )控件的使用。
在该例程中,5 个 单选控件分为 2 组,分别为第一组的 2 个单选控件和第二组的 3 个 单选控件。我们的程序将 5 个控件添加到主窗口中。
对于第一组的 2 个 单选控件,使用 Qt 默认的分组功能,即将这两个控件放在主窗口中,因为 QRadioButton 是继承自 QAbstractButton 的,所以它的自动互斥特性会自动生效,即任何一组中多个 QRadioButton 控件只能有一个被选中。
对于第二组的 3 个 单选控件,使用 按钮组(QButtonGroup )来实现互斥。这里我们新建一个 QButtonGroup 控件,将其加入到主窗口中,然后将窗口中的 3 个单选控件分别添加到该 QButtonGroup 中。这样,当选中其中某个单选控件时,其他组内的单选控件会自动取消选择。可以通过 setChecked() 函数设置初始选中状态,程序启动后,用户可以通过鼠标或触摸选择其他单选控件。
5.1.2 程序执行效果
其中
开关一
和开关二
为第一组,选择一
、选择二
、选择三
第二组。
5.2 生成项目
打开 Qt Creator 并创建一个新的 应用程序项目_radiobutton,选择了Widget基类,不要勾选“Generate form”,将两个配置好的Kits同时选上,项目新建完成如下图。(详细的项目新建过程参见:《Qt常用的按钮控件编程(一)》)
5.3 添加资源文件
在 Qt 中,可以使用资源文件(.qrc 文件)将一些静态资源(如图像、音频等)打包到应用程序中,以方便统一管理和部署。在本例程中,在images 文件夹中准备了4张图片,拷贝到本项目路径中,下图演示了如何将资源添加到项目中。
5.3.1 添加图片资源
- 在项目目录中右键点击 Resources 目录,选择 Add New… ,并选择 Qt -> Qt Resource File。
在打开的对话框中输入名称(最好与文件名一致),然后点击 Next。
输入资源文件的名称(自行定义)和位置,然后点击“下一步”。
在 Qt Creator 中新建资源文件后,默认会进入 res.qrc 文件编辑模式(如果关闭了,可以右键这个文
件点击选择“Open in Editor”),为了方便分类管理文件,我们可以使用 Add Prefix 功能为资源文件添加前缀,前缀的格式应该为类似文件系统中的路径格式,例如 /images。
为了确保路径正确,前缀中的 / 是必需的,它在资源文件引用时是路径分隔符,起到类似 Linux 下根节点的作用,我们现在第⑪处添加了前缀/。
添加了前缀后,我们添加资源图片,放在/images 前缀的下面。这里我们导入在本项目路径 images 文件夹中的4张图片,添加完成需要按“Ctrl + S”保存 res.qrc 才会看到左边的结果。添加完成如下图。
5.3.2 添加 qss 文件
QSS 文件是使用 Qt 程序相关联的样式表文件。它由 GUI 元素的外观和感觉,包括布局,颜色,鼠标的行为,大小和字体。它的风格,一个可以合并到一个 UI(用户界面)。与 HTML 的 CSS 类似,Qt 的样式表是纯文本的格式定义,在应用程序运行时可以载入和解析这些样式定义,从而使应用程序的界面呈现不同的效果。
如上图加入一个空白文件,新建的文件名 style.qss 文件,如下图,默认添加到项目的路径下,后面步骤采用默认,直至完成。
编辑style.qss,保存,最后完成的项目如下图所示:
style.qss文件内容:
/* 第一组 QRadioButton 设置 */
QRadioButton#radiogroup1{
spacing: 2px;
color: red;
}
QRadioButton#radiogroup1::indicator {
width: 45px;
height: 30px;
}
QRadioButton#radiogroup1::indicator:unchecked {
image: url(:/images/switch_off.png);
}
QRadioButton#radiogroup1::indicator:checked {
image: url(:/images/switch_on.png);
}
/* 第二组 QRadiobutton 设置 */
QRadioButton#radiogroup2 {
spacing: 2px;
color: blue;
}
QRadioButton#radiogroup2::indicator {
width: 45px;
height: 30px;
}
QRadioButton#radiogroup2::indicator:unchecked {
image: url(:/images/radiobutton-off.png);
}
QRadioButton#radiogroup2::indicator:checked {
image: url(:/images/radiobutton-on.png);
}
5.4 完成代码编辑
5.4.1 修改项目文件 _radiobutton.pro
1 QT += core gui
2
3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
4
5 CONFIG += c++11
6
7 # You can make your code fail to compile if it uses deprecated APIs.
8 # In order to do so, uncomment the following line.
9 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
10
11 SOURCES += \
12 main.cpp \
13 widget.cpp
14
15 HEADERS += \
16 widget.h
17
18 # Default rules for deployment.
19 qnx: target.path = /tmp/$${TARGET}/bin
20 else: unix:!android: target.path = /opt/$${TARGET}/bin
21 !isEmpty(target.path): INSTALLS += target
22
23 RESOURCES += \
24 res.qrc
25
26
27 # 根据使用的 Qt 版本设置编译条件
28 greaterThan(QT_MAJOR_VERSION, 4) {
29 # 如果使用的是 Qt 5 或者更新版本
30 message("使用的是 Qt 5版本")
31
32 } else {
33 # 如果使用的是 Qt 4 或者更早的版本
34 message("使用的是 Qt 4版本")
35 DEFINES += QT_ARM_PLATFORM
36 QMAKE_CXXFLAGS += -std=c++11
37 QMAKE_CXXFLAGS += -Wno-psabi -Wno-deprecated-declarations
38
39 LIBS += -lts
40
41 }
我们在系统生成的项目文件中使用条件编译增加目标为qt4-arm时的代码:
5.4.2 修改 main.cpp
1 #include "widget.h"
2
3 #include <QApplication>
4
5 #ifdef QT_ARM_PLATFORM
6 #include <QTextCodec>
7 #endif
8
9 /* 引入 QFile */
10 #include <QFile>
11
12 int main(int argc, char *argv[])
13 {
14 QApplication a(argc, argv);
15
16 #ifdef QT_ARM_PLATFORM
17 //解决Qt4中文乱码
18 QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
19 QTextCodec::setCodecForTr(QTextCodec::codecForName("system")); //若英文系统,则用GBK
20 QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
21 QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
22 #endif
23
24 /* 指定文件 */
25 QFile file(":/style.qss");
26
27 /* 判断文件是否存在 */
28 if (file.exists() ) {
29 /* 以只读的方式打开 */
30 file.open(QFile::ReadOnly);
31 /* 以字符串的方式保存读出的结果 */
32 QString styleSheet = QLatin1String(file.readAll());
33 /* 设置全局样式 */
34 qApp->setStyleSheet(styleSheet);
35 /* 关闭文件 */
36 file.close();
37 }
38
39 Widget w;
40 w.show();
41 return a.exec();
42 }
-
为了解决当程序运行在arm架构系统时,中文显示文乱码问题,根据从.pro获得的宏QT_ARM_PLATFORM作为编译条件,判断如果系统运行在arm架构,则程序包含文本字符串转换,解决Qt4中文乱码问题。
-
第 24 行至 37 行,读取 style.qss 的内容。并设置全局样式。
5.4.3 修改 widget.h
1 #ifndef WIDGET_H
2 #define WIDGET_H
3
4 #include <QWidget>
5
6 /* 引入 QRadioButton */
7 #include <QRadioButton>
8
9 /* 引入 QButtonGroup */
10 #include <QButtonGroup>
11 class Widget : public QWidget
12 {
13 Q_OBJECT
14
15 public:
16 Widget(QWidget *parent = nullptr);
17 ~Widget();
18
19 private:
20 /* 声明5个 QRadioButton 对象 */
21 QRadioButton *radioButton1;
22 QRadioButton *radioButton2;
23 QRadioButton *radioButton3;
24 QRadioButton *radioButton4;
25 QRadioButton *radioButton5;
26 /* 声明 QButtonGroup对象 */
27 QButtonGroup *button_group;
28 };
29 #endif // WIDGET_H
5.4.4 修改 widget.cpp
1 #include "widget.h"
2
3 Widget::Widget(QWidget *parent)
4 : QWidget(parent)
5 {
6 /* 主窗体设置位置和显示的大小 */
7 this->setGeometry(0, 0, 800, 480);
8
9 /*将主窗口背景色设置为天蓝色(不透明度为 100%)*/
10 this->setStyleSheet("Widget { background-color: rgba(135, 206, 250, 100%); }");
11
12 /* 实例化5个QRadioButton单选按钮对象 */
13 radioButton1 = new QRadioButton(this);
14 radioButton2 = new QRadioButton(this);
15 radioButton3 = new QRadioButton(this);
16 radioButton4 = new QRadioButton(this);
17 radioButton5 = new QRadioButton(this);
18
19 // 创建一个按钮组 QButtonGroup 对象
20 button_group = new QButtonGroup(this);
21
22 /* 设置第一组两个 QRadioButton 的位置和显示大小 */
23 radioButton1->setGeometry(280, 140, 100, 50);
24 radioButton2->setGeometry(420, 140, 100, 50);
25
26 /* 设置第二组3个 QRadioButton 的位置和显示大小 */
27 radioButton3->setGeometry(140, 290, 100, 50);
28 radioButton4->setGeometry(340, 290, 100, 50);
29 radioButton5->setGeometry(540, 290, 100, 50);
30
31 /* 设置第一组两个 QRadioButton 的显示文本 */
32 radioButton1->setText("开关一");
33 radioButton2->setText("开关二");
34
35 /* 设置第二组3个 QRadioButton 的显示文本 */
36 radioButton3->setText("选择一");
37 radioButton4->setText("选择二");
38 radioButton5->setText("选择三");
39
40 /* 第一组 QRadioButton 使用样式表1设置 */
41 radioButton1->setObjectName("radiogroup1");
42 radioButton2->setObjectName("radiogroup1");
43
44 /* 第二组 QRadioButton 使用样式表2设置 */
45 radioButton3->setObjectName("radiogroup2");
46 radioButton4->setObjectName("radiogroup2");
47 radioButton5->setObjectName("radiogroup2");
48
49 /*第一组的2个 单选控件,使用 Qt 默认的分组功能*/
50
51 /*将第二组三个单选按钮对象添加到按钮组 button_group*/
52 button_group->addButton(radioButton3);
53 button_group->addButton(radioButton4);
54 button_group->addButton(radioButton5);
55
56 /*设置第二组按钮成员为互斥*/
57 button_group->setExclusive(true);
58
59 /* 第一组设置初始状态,radioButton1 的 Checked 为 true,另一个为 false*/
60
61 radioButton1->setChecked(true);
62 radioButton2->setChecked(false);
63
64
65 /* 第二组设置初始状态,rradioButton3 的 Checked 为 true,另两个为 false*/
66 radioButton3->setChecked(true);
67 radioButton4->setChecked(false);
68 radioButton5->setChecked(false);
69 }
70
71 Widget::~Widget()
72 {
73 }
5.5 切换Kit,获得运行在不同系统中的运行的执行文件
点击窗口左边的Debug,可以选择编译运行在不同平台上的可执行文件,arm-v7为arm架构的设备,使用Qt4库,而桌面则是当前ubuntu系统,使用Qt5。
Qt5编译完成的可执行程序_qcheckbox
,存放在项目目录的build-_qcheckbox-unknown-Debug/
文件夹下,Qt4编译完成的可执行程序_qcheckbox
,存放在项目目录的build-_qcheckbox-arm_v7-Debug/
文件夹下。
5.6 程序中的qt机制
5.6.1 资源(Resource)
在 Qt 中,资源(Resource)指的是应用程序中的特殊文件,如图像、文本等。Qt资源系统将这些资源文件封装为资源文件(Resource File),并将它们存储在.qrc文件中,然后使用rcc工具(编译时rcc工具会自动被调用)将.qrc文件编译成一种二进制格式,并与应用程序的可执行文件或库一并打包存储。
通过 Qt 提供的资源管理类可以方便的访问这些资源,这样可以有效地避免了文件路径问题以及繁琐的资源查找流程。使用 Qt 资源系统,可以使开发者更加方便地管理和使用应用程序中的资源,提高应用程序的质量和开发效率。
在我们的_radiobutton项目中,将4个图片文件和一个.qss样式表文件作为资源文件添加到.qrc文件。
5.6.1.1 qss 样式表文件
.qss 文件是一个 Qt 样式表文件,用于为应用程序中的部件(例如按钮、文本框、标签等)定义自定义样式。它可以包含一些常规的样式属性,如字体、颜色、背景和边框设置,也可以包含复杂的样式设置,如图像背景、渐变色和阴影效果。
使用 .qss 文件,可以改变 Qt 部件的外观和行为,以匹配应用程序的主题和风格。可以选择遵循现有的样式规则,也可以通过定义自己的样式规则来创建全新的外观效果。.qss 文件是一种非常灵活和强大的方法,可以实现几乎任何自定义样式的要求。
事实上,Qt 应用程序中的样式文件名称可以完全自定义,只要在应用程序中正确地引用了它们即可。将样式表文件保存为 .qss 扩展名是一种推荐的做法,因为它可以让其他开发人员快速理解某个文件的用途。为节省时间并简化管理,通常建议将样式表文件保存在应用程序的一个单独目录中,并使用一致的命名约定。例如,可以将所有的样式表文件保存在 styles 目录下,并按照 theme_name.qss 的格式命名,其中 theme_name 是想要使用的主题名称。这样做可以使文件命名和管理更加清晰,并使代码更加易于维护。
如果不想使用样式表文件,仍然可以使用 setStyleSheet() 方法将样式定义直接嵌入到 Qt 应用程序的代码中,这样的做法会让应用程序的代码和布局变得混乱且难以维护。
5.6.1.2 图片文件
QRadioButton 支持的图片文件类型包括:
PNG 格式:PNG 格式是 Qt 支持的最常用的图片格式之一,它支持透明度和 alpha 通道,并且可以轻松地在不同的平台上进行交互和显示。
BMP 格式:BMP 格式也是 Qt 支持的常用图片格式之一,它可以在不同的平台上轻松地进行交互和显示。
GIF 格式:GIF 格式是一种支持动画和透明度的图片文件格式,但是它有一些限制,比如只支持 256 色。
JPEG 格式:JPEG 格式是一种常用的压缩图片格式,它可以在 Qt 中使用,并且可以配置图片质量。
SVG 格式:SVG 是一种矢量图形格式,可以在 Qt 中使用,并支持缩放和动画。
总的来说,QRadioButton 支持很多种图片格式,主要包括 PNG、BMP、GIF、JPEG 和 SVG 等,开发者可以根据自己的需要选择合适的图片格式。
5.6.2 按钮组 QButtonGroup
ButtonGroup 是用于管理一组按钮的控件。它能够在一组互斥的按钮中,确保只有一个按钮被选中。当用户点击这组按钮中的一个按钮时,QButtonGroup 将会自动检测其中的选中状态并更新其它按钮的选中状态,以确保只有一个按钮被选中。
QButtonGroup 可以管理多种类型的按钮控件,包括:
- QCheckBox:复选框。
- QRadioButton:单选框。
- QPushButton:普通按钮。
- QAbstractButton 或其子类:抽象按钮或其子类,如 QToolButton、QCommandLinkButton、QAbstractSpinBox 和 QComboBox 等。
QButtonGroup 可以通过 setExclusive() 函数实现对其管理的一组按钮的互斥性控制.
虽然 QButtonGroup 可以像容器一样管理一组按钮,但事实上 QButtonGroup 并不是容器控件,而是 Qt 的一种支持控件。容器控件用于管理(即容纳)其他控件,例如 QWidget、QFrame、QSplitter 等,可以将多个控件作为其子控件添加到其内部,形成一个层次化的控件树。而 QButtonGroup 只是用于管理一组互斥的按钮,它并没有作为容器控件来管理其他控件。
总结
本例程为QRadioButton 单选按钮编程。通过这个例子,初步了解QT管理资源机制,以及如何分组管理QRadioButton 单选按钮。项目演示如何使用默认的分组和 QButtonGroup 进行互斥设置,保证多个选项所在的组内只有一个被选中。项目使用样式表文件将两组按钮使用不同的样式表进行外观设置。
文章中使用的例程和内容都是在chatgpt的帮助下完成的,例程经过测试通过。