QT控件:【控件概述】【QWidget核心体系】【按钮类控件】【显示类控件】
目录
一. 控件概述
二. QWidget核心体系
2.1 enabled
2.2 geometry
2.3 windowTitle
2.4 windowIcon
获取当前的工作目录
qrc机制
2.5 windowOpacity
调整窗口透明度
2.6 cursor
自定义光标形式
2.7 font
在代码中设置字体属性
2.8 toolTip
设置按钮的 toolTip
2.9 focusPolicy
2.10 styleSheet
代码:设置夜间模式
三. 按钮类控件
3.1 PushButton
带图标的按钮
给按钮添加快捷键
3.2 Radio Button
选择性别
click,press,release,toggled的区别
单选框分组
3.3 Check box
获取复选按钮的取值
四. 显示类控件
4.1 Qlabel
显示不同格式的文本
显示图片
文本对齐,自动换行,缩进,边距
设置伙伴
4.2 LCD number
倒计时
4.3 ProgressBar
设置进度条按时间增长
设置红色的进度条
4.4 Calendar Widget
获取选中的日期
一. 控件概述
Widget 是 Qt 中的核心概念。英文原义是 "小部件",我们此处也把它翻译为 "控件"。
控件是构成一个图形化界面的基本要素。
像上述示例中的,按钮、列表视图、树形视图、单行输入框、多行输入框、滚动条、下拉框等,都可以称为 “控件”。
Qt 作为一个成熟的 GUI 开发框架,内置了大量的常用控件。这一点在 Qt Designer 中就可以看到端倪。
并且 Qt 也提供了 “自定义控件” 的能力,可以让程序员在现有控件不能满足需求的时候,对现有控件做出扩展,或者手动开发出新的控件。
这些全是控件
二. QWidget核心体系
在 Qt 中,使用 QWidget 类表示 “控件”。像按钮、视图、输入框、滚动条等具体的控件类,都是继承自 QWidget。
可以说,QWidget 中就包含了 Qt 整个控件体系中,通用的部分。
在 Qt Designer 中,随便拖一个控件过来,选中该控件,即可在右下方看到 QWidget 中的属性。
2.1 enabled
描述一个控件是否可用
• 所谓“禁用”指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。
• 如果一个 widget 被禁用,则该 widget 的子元素也被禁用。
可以通过代码看一下:
用另一个按钮开启或者关闭按钮:
QObject 的 objectName 属性介绍:
QObject 是 QWidget 的父类。里面最主要的属性就是 objectName 。在一个 Qt 程序中,objectName 相当于对象的身份标识,彼此之间不能重复。
在使用 Qt Designer 时,尤其是界面上存在多个 widget 的时候,可以通过 objectName 获取到指定的 widget 对象。
Qt Designer 生成的 ui 文件,本身是 xml 格式的。qmake 会把这个 xml 文件转换成 C++ 的 .h 文件(这个文件生成在 build 目录中),构成一个 ui_widget 类。
每个 widget 的 objectName 最终就会成为 ui_widget 类的属性名字。
最终这个类的实例,就是 Ui::Widget *ui ,因此就可以通过形如 ui->pushButton 或者 ui->pushButton_2 这样的代码获取到界面上的 widget 对象了。
2.2 geometry
位置和尺寸,其实是四个属性的统称:
・x 横坐标
・y 纵坐标
・width 宽度
・height 高度
这里就写一个控制一个上下左右的按钮:
五个按钮的 objectName 分别为 pushButton_target、pushButton_up、pushButton_down、pushButton_left、pushButton_right。
使用move也可以。
Window frame
如果 widget 作为一个窗口(带有标题栏、最小化、最大化、关闭按钮),那么在计算尺寸和坐标的时候就有两种算法:包含 window frame 和不包含 window frame。
其中 x ()、y ()、frameGeometry ()、pos ()、move () 都是按照包含 window frame 的方式来计算的。
其中 geometry ()、width ()、height ()、rect ()、size () 则是按照不包含 window frame 的方式来计算的。
当然,如果一个不是作为窗口的 widget,上述两类方式得到的结果是一致的。
先来看一个现象,在Widget的构造函数里:
这里打印的值是一样的:
现在我创建一个按钮来触发槽,在Widget构造函数外:
为什么会有这样的影响?
因为在Widget构造函数中,Widget正在构造,还没有假如到window frame中,看不到window frame 的影响
2.3 windowTitle
注意!上述设置操作针对不同的 widget 可能会有不同的行为。 如果是顶层 widget(独立窗口),这个操作才会有效。 如果是子 widget,这个操作无任何效果。
较与简单了。
2.4 windowIcon
先在 D 盘中放一个图片,名字为 rose.jpg
注意:Windows 下路径的分隔符可以使用 / 也可以使用 \ 。但是如果在 字符串 中使用 \ ,需要写作转义字符的形式 \\ 。因此我们还是更推荐使用 / 。
C++11中引入了raw string解决上面的问题,所有的字符串都不会被转义,也就是r("d:\rose.jpg")
于此同时,程序在任务栏中的图表也发生改变.
获取当前的工作目录
进入上述构建目录,把里面的 exe 拷贝到其他目录中,比如 D: 中。再次执行程序,可以看到当前工作目录已经发生改变。
qrc机制
qrc 文件是一种 XML 格式的资源配置文件(后缀为.qrc),它用 XML 记录硬盘上的文件和对应的随意指定的资源名称。应用程序通过资源名称来访问这些资源。
在 Qt 开发中,可以通过将资源文件添加到项目中来方便地访问和管理这些资源。这些资源文件可以位于 qrc 文件所在目录的同级或其子目录下。
在构建程序的过程中,Qt 会把资源文件的二进制数据转成 cpp 代码,编译到 exe 中。从而使依赖的资源变得 “路径无关”。这种资源管理机制并非 Qt 独有,很多开发框架都有类似的机制。例如 Android 的 Resources 和 AssetManager 也是类似的效果。
1) 右键项目,创建一个 Qt Resource File(qrc 文件),文件名随意起(不要带中文),此处叫做 resource.qrc 。
2) 在 qrc 编辑器中,添加前缀。
此处我们前缀设置成 / 即可。
所谓的前缀,可以理解成 “目录”。这个前缀决定了后续我们如何在代码中访问资源。
3) 在 资源编辑器 中,点击 add Files 添加资源文件。此处我们需要添加的是 rose.jpg
注意:添加的文件必须是在 qrc 文件的同级目录,或者同级目录的子目录中。因此我们需要把之前 D 盘中的 rose.jpg 复制到上述目录中。
添加完毕后,可以在 资源编辑器 中看到添加好的文件。
4) 在代码中使用rose.jpg
注意上述路径的访问规则:
・使用 : 作为开头,表示从 qrc 中读取资源。
• / 是上面配置的前缀。
• rose.jpg 是资源的名称。
需要确保代码中编写的路径和添加到 qrc 中资源的路径匹配,否则资源无法被访问(同时也不会有报错提示)。
5) 运行后:
接下来,我们可以进入到项目的构建目录,可以看到,目录中多了一个 qrc_resource.cpp 文件。直接打开这个文件,可以看到类似如下代码:
上述代码其实就是通过 unsigned char 数组,把 rose.jpg 中的每个字节都记录下来。这些代码会被编译到 exe 中。后续无论 exe 被复制到哪个目录下,都确保能够访问到该图片资源。
优点:确保了图片,字体,声音等资源能够真正做到 "目录无关", 无论如何都不会出现资源丢失的情况.
缺点:不适合管理体积大的资源。如果资源比较大 (比如是几个 MB 的文件), 或者资源特别多,生成的最终的 exe 体积就会比较大,程序运行消耗的内存也会增大,程序编译的时间也会显著增加.
2.5 windowOpacity
调整窗口透明度
这里有个问题就这里的数值并不是真正的变化0.1:
注意,C++ 中 float 类型遵守 IEEE 754 标准,因此在进行运算的时候会有一定的精度误差。因此 1 - 0.1 的数值并非是 0.9 。
2.6 cursor
可以使用ui修改手势
使用代码:
自定义光标形式
1) 创建 qrc 资源文件,添加前缀 / ,并加入 rose.jpg 。
2.7 font
关于QFont
在代码中设置字体属性
2.8 toolTip
toolTip 只是给用户看的. 在代码中一般不需要获取到 toolTip.
设置按钮的 toolTip
2.9 focusPolicy
设置控件获取到焦点的策略。比如某个控件能否用鼠标选中或者能否通过 tab 键选中.
所谓 "焦点", 指的就是能选中这个元素。接下来的操作 (比如键盘操作), 就都是针对该焦点元素进行的了。这个对于 输入框,单选框,复选框等控件非常有用的.
这个事情就和 war3 或者 sc2 中,先选中单位,再下达命令是一样的.
理解不同的 focusPolicy
1) 在界面上创建四个单行输入框 (Line Edit)
2) 修改四个输入框的 focusPolicy 属性为 Qt::StrongFocus (默认取值, 一般不用额外修改)
此时运行程序,可以看到,使用鼠标单击 /tab, 就可以移动光标所在输入框。从而接下来的输入就是针对这个获取焦点的输入框展开的了.
3) 修改第二个输入框的 focusPolicy 为 Qt::NoFocus , 则第二个输入框不会被 tab / 鼠标左键选中.
此时这个输入框也就无法输入内容了.
4)修改第二个输入框 focusPolicy 为 Qt::TabFocus , 则只能通过 tab 选中,无法通过鼠标选中.
5)修改第二个输入框 focusPolicy 为 Qt::ClickFocus , 则只能通过鼠标选中,无法通过 tab 选中.
2.10 styleSheet
通过 CSS 设置 widget 的样式.
CSS (Cascading Style Sheets 层叠样式表) 本身属于网页前端技术。主要就是用来描述界面的样式.
所谓 "样式", 包括不限于 大小,位置,颜色,间距,字体,背景,边框等.
我们平时看到的丰富多彩的网页,就都会用到大量的 CSS.
Qt 虽然是做 GUI 开发,但实际上和 网页前端 有很多异曲同工之处。因此 Qt 也引入了对于 CSS 的支持.
CSS 中可以设置的样式属性非常多。基于这些属性 Qt 只能支持其中一部分,称为 QSS (Qt Style Sheet)
此处的语法格式同 CSS, 使用键值对的方式设置样式。其中键和值之间使用:分割。键值对之间使用;分割.
另外,Qt Designer 只能对样式的基本格式进行校验,不能检测出哪些样式不被 Qt 支持。比如 textalign: center 这样的文本居中操作,就无法支持.
代码:设置夜间模式
TextIdit
编写按钮的颜色:
・#333 是深色,但是没那么黑.
・#fff 是纯白色.
・#000 是纯黑色.
计算机中使用 "像素" 表示屏幕上的一个基本单位 (也就是一个发亮的光点).
每个光点都使用三个字节表示颜色,分别是 R (red), G (green), B (blue) 一个字节表示 (取值范围是 0-255, 或者 0x00-0xFF).
混合三种不同颜色的数值比例,就能搭配出千千万万的颜色出来.
・rgb (255, 0, 0) 或者 #FF0000 或者 #F00 表示纯红色.
・rgb (0, 255, 0) 或者 #00FF00 或者 #0F0 表示纯绿色.
・rgb (0, 0, 255) 或者 #0000FF 或者 #00F 表示纯蓝色.
・rgb (255, 255, 255) 或者 #FFFFFF 或者 #FFF 表示纯白色.
・rgb (0, 0, 0) 或者 #000000 或者 #000 表示纯黑色.
当然,上述规则只是针对一般的程序而言是这么设定的。实际的显示器,可能有 8bit 色深或者 10bit 色深等,实际情况会更加复杂.
三. 按钮类控件
3.1 PushButton
使用 QPushButton 表示一个按钮。这也是当前我们最熟悉的一个控件了.
QPushButton 继承自 QAbstractButton . 这个类是一个抽象类。是其他按钮的父类.
在Qt Designer也可以看出继承关系:
在 QAbstractButton
中,与 QPushButton
相关性较大的属性包括:
QAbstractButton 作为 QWidget 的子类,当然也继承了 QWidget 的属性。上面介绍的 QWidget 里的各种属性用法,对于 QAbstractButton 同样适用。因此表格仅列出 QAbstractButton 独有的属性.
Qt 的 api 设计风格是非常清晰的。此处列出的属性都是可以 获取 和 设置 的。例如,使用 text () 获取按钮文本;使用 setText () 设置文本.
带图标的按钮
创建qrc之后,再创建一个按钮:
给按钮添加快捷键
使用函数setShortcut创建快捷键
对于QKeySequence,我们按下的按键可能是组合键:
上面的设置快捷键的方式是使用按键 名字,还可以使用按键的枚举:
3.2 Radio Button
QRadioButton 是单选按钮。可以让我们在多个选项中选择一个.
作为 QAbstractButton 和 QWidget 的子类,上面介绍的属性和用法,对于 QRadioButton 同样适用.
QAbstractButton 中和 QRadioButton 关系较大的属性
选择性别
1) 在界面上创建一个 label, 和 3 个 单选按钮
2) 修改 widget.cpp, 编辑三个 QRadioButton 的 slot 函数.
还能设置默认被选中的性别,并且禁用other选项:
click,press,release,toggled的区别
创建4个按钮
给 1 创建 clicked 槽函数, 给 2 创建 pressed 槽函数, 给 3 创建 released 槽函数, 给 4 创建 toggled 槽函数.
运行之后:
・clicked 是一次鼠标按下 + 鼠标释放触发的.
・pressed 是鼠标按下触发的.
・released 是鼠标释放触发的.
・toggled 是 checked 属性改变时触发的.
总的来说,toggled 是最适合 QRadioButton 的.因为是单选
单选框分组
我们希望每一组内部来控制排他, 但是组和组之间不能排他.
引入 QButtonGroup进行分组.
3.3 Check box
QCheckBox 表示复选按钮。可以允许选中多个.
和 QCheckBox 最相关的属性也是 checkable 和 checked , 都是继承自 QAbstractButton .
至于 QCheckBox 独有的属性 tristate 用来实现 "三态复选框" . 这个东西比较冷门
获取复选按钮的取值
四. 显示类控件
4.1 Qlabel
显示不同格式的文本
建立三个Qlabel
显示图片
把图片导入qrc中:
虽然是设置了跟窗口一样大,但是这里的图片 是没有那么大的,它自己本身也有大小:
可以设置自动拉伸:
但是如果我拉伸这个窗口,图又会变形:
用户的操作可以分为信号和实践,
可以在 Widget 中重写 resizeEvent 函数
当用户在拖动窗口的时候,就会触发resize事件,是连续变化的,也就是说,拖动的过程会是一系列的resizeEvent事件
文本对齐,自动换行,缩进,边距
1)创建四个 label, objectName 分别是 label 到 label_4
并且在 QFrame 中设置 frameShape 为 Box (设置边框之后看起来会更清晰一些)
QFrame 是 QLabel 的父类。其中 frameShape 属性用来设置边框性质.
・QFrame::Box :矩形边框
・QFrame::Panel :带有可点击区域的面板边框
・QFrame::WinPanel :Windows 风格的边框
・QFrame::HLine :水平线边框
・QFrame::VLine :垂直线边框
・QFrame::StyledPanel :带有可点击区域的面板边框,但样式取决于窗口主题
结果:
设置伙伴
此处把 label 中的文本设置为 "快捷键 &A" 这样的形式.
其中 & 后面跟着的字符, 就是快捷键.
可以通过 alt + A 的方式来触发该快捷键.
但是注意, 这里的快捷键和 QPushButton 的不同. 需要搭配 alt 和单个字母的方式才能触发.
执行程序的时候必须按下Alt + a或者Alt + b:
4.2 LCD number
QLCDNumber 是一个专门用来显示数字的控件. 类似于"老式计算器"的效果.
倒计时
思路就是创建时间器,倒计时,判断value是否小于0,然后改变lcdNumber的显示:
定时器一到就会发送timeout信号,这里connect就行:
能否在构造函数中使用sleep的方式?
绝对不可以,循环会使Widget的构造函数无法完成。界面就无法显示了。
上述代码如果是在 Widget 构造函数中, 另起一个线程, 在新线程中完成 循环 + sleep 是否可以呢? 代码形如
这个代码同样是不行的。Qt 中规定,任何对于 GUI 上内容的操作,必须在主线程中完成。像 Widget 构造函数,以及 connect 连接的 slot 函数,都是在主线程中调用的。而我们自己创建的线程则不是。
当我们自己的线程中尝试对界面元素进行修改时,Qt 程序往往会直接崩溃。
这样的约定主要是因为 GUI 中的状态往往是牵一发而动全身的,修改一个地方,就需要同步地对其他内容进行调整。
比如调整了某个元素的尺寸,就可能影响到内部的文字位置,或者其他元素的位置。这里一连串的修改,都是需要按照一定的顺序来完成的。
由于多线程执行的顺序无法保障,因此 Qt 从根本上禁止了其他线程修改 GUI 状态,避免后续的一系列问题。
4.3 ProgressBar
设置进度条按时间增长
在实际开发中,进度条的取值往往是根据当前任务的实际进度来进行设置的。
比如需要读取一个很大的文件,就可以获取文件的总大小和当前读取完毕的大小,来设置进度条的比例。
由于上面我们介绍了 Qt 禁止在其他线程修改界面,因此进度条的更新往往也需要搭配定时器来完成。
通过定时器周期触发信号,主线程调用对应的 slot 函数,再在 slot 函数中对当前的任务进度进行计算,并更新进度条的界面效果。
设置红色的进度条
当然还是用QSS:
4.4 Calendar Widget
获取选中的日期
依旧是它的信号: