文章目录
一、布局管理器
1. 绝对定位
2. 布局定位
3. 水平/垂直/网格布局
4. 实际练习
二、自定义控件
1. ui 界面实现
2. 代码实现
2.1 小控件头文件 smallwidget.h
2.2 小控件源文件 smallwidget.cpp
三、QT 样式表
1. QT 样式规则
1.1 基本介绍
1.2 实际演示
2. QT 盒子模型
3. 子控件
4. 伪状态
5. 冲突解决
6. 选择器类型
由于每次代码都是在原有程序上修改,因此除了新建项目,不然一般会在学完后统一展示代码。
提示:具体项目创建流程和注意事项见
QT 学习笔记(一)
提示:具体项目准备工作和细节讲解见
QT 学习笔记(二)
一、布局管理器
- 生成一个新的项目,具体步骤过程见提示。
- 所谓的 GUI 界面,就是一堆组件的叠加。我们创建一个窗口,把按钮放在上面,把图标放在上面,这样就成了一个界面。在放置时,组件的位置尤其重要。我们必须要指定组件放在哪里,以便窗口能够按照我们需要的方式进行渲染。这就涉及到组件定位的机制
- 一般情况下布局都是通过 ui 控制器及进行布局,通过代码布局的话会显得很抽象。
- QT 提供了两种组件定位机制:绝对定位和布局定位。
1. 绝对定位
绝对定位就是一种最原始的定位方法:给出这个组件的坐标和长宽值。
这样,QT 就知道该把组件放在哪里以及如何设置组件的大小。
但是这样做带来的一个问题是,如果用户改变了窗口大小,比如点击最大化按钮或者使用鼠标拖动窗口边缘,采用绝对定位的组件是不会有任何响应的。
因为并没有告诉 QT ,在窗口变化时,组件是否要更新自己以及如何更新。或者,还有更简单的方法,就是禁止用户改变窗口大小。
2. 布局定位
布局定位:只要把组件放入某一种布局,布局由专门的布局管理器进行管理。当需要调整大小或者位置的时候,Qt 使用对应的布局管理器进行调整。
布局定位完美的解决了使用绝对定位的缺陷。
QT 提供的布局中以下三种是我们最常用的:
(1)QHBoxLayout:按照水平方向从左到右布局。
(2)QVBoxLayout:按照竖直方向从上到下布局。
(3)QGridLayout:在一个网格中进行布局,类似于 HTML 的 table。
3. 水平/垂直/网格布局
- 只有当 ui 界面当中有控件,布局功能才会打开,在这里首先放置三个按钮。
- QSpinBox 就是只能输入数字的输入框,并且带有上下箭头的步进按钮。
- QSlider 则是带有滑块的滑竿。
- 在网格布局之前,我们要先大致摆好我们要布局的样子,之后在点击网格布局按钮。
- 在布局时,很有可能需要借助弹簧操作,如下:
我想让按钮水平布局后不要直接变成一整行,使其保持在中间,此时,我们就要使用弹簧功能(在放置之前,需要先取消整体布局的格式,不然仍会按照之前的格式进行布局)
分裂器水平布局和分裂器垂直布局的功能是可以手动拖动界面。
4. 实际练习
- 记得添加资源,我们才可以通过 Label 标签调用我们想要使用的图片和动画。
- 布局本身很简单,但是需要大规模练习,才可以布置出好看的布局。
- (虽然有点丑,但基本实现预想功能。)
二、自定义控件
在搭建 QT 窗口界面的时候,在一个项目中很多窗口,或者是窗口中的某个模块会被经常性的重复使用。
一般遇到这种情况我们都会将这个窗口或者模块拿出来做成一个独立的窗口类,以备以后重复使用。
在使用 QT 的 ui 文件搭建界面的时候,工具栏栏中只为我们提供了标准的窗口控件,如果我们想使用自定义控件怎么办?
以上一次做的登录界面为例,添加一个微调和滑块的功能。
1. ui 界面实现
- 这种方法没有任何难度。
2. 代码实现
先在 ui 界面预定位置放一个 Widget 容器。
然后,新建一个 smallwidget 小控件。
那么这个 smallwidget 可以作为独立的窗口显示,也可以作为一个控件来使用。
打开 QT 的 ui 文件,因为 smallwidget 是派生自 QWidget 类,所以需要在 ui 文件中先放入一个 QWidget 控件,然后再上边鼠标右键。
弹出提升窗口部件对话框。
- 添加之后,类名会显示到上边的列表框中,然后单击提升按钮,完成操作。我们可以看到,这个窗口对应的类从原来的 QWidget 变成了 smallwidget 。
- 此时运行程序,会产生如下变化:
2.1 小控件头文件 smallwidget.h
#ifndef SMALLWIDGET_H #define SMALLWIDGET_H #include <QWidget> #include <QSpinBox> #include <QSlider> #include <QHBoxLayout> class smallwidget : public QWidget { Q_OBJECT public: explicit smallwidget(QWidget *parent = nullptr); public slots: signals: private: QSpinBox* spin; QSlider* slider; public slots: }; #endif // SMALLWIDGET_H
2.2 小控件源文件 smallwidget.cpp
#include "smallwidget.h" #include <QSpinBox> #include <QSlider> #include <QHBoxLayout> smallwidget::smallwidget(QWidget *parent) : QWidget(parent) { QSpinBox *spin = new QSpinBox(this); QSlider *slider = new QSlider(Qt::Horizontal, this); // 创建布局对象 QHBoxLayout* layout = new QHBoxLayout; // 将控件添加到布局中 layout->addWidget(spin); layout->addWidget(slider); // 将布局设置到窗口中 setLayout(layout); // 添加消息响应 connect(spin,static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), slider, &QSlider::setValue); connect(slider, &QSlider::valueChanged, spin, &QSpinBox::setValue); }
三、QT 样式表
QT 样式表的思想很大程度上是来自 HTML 的层叠式样式表(CSS),通过调用 QWidget :: setStyleSheet() 或 QApplication :: setStyleSheet() ,可以为一个独立的子部件,整个窗口,甚至是整个应用程序指定一个样式表。
1. QT 样式规则
1.1 基本介绍
样式表包含了一系列的样式规则,每个样式规则由选择器 ( selector) 和声明 ( decla-ration) 组成。选择器指定了受该规则影响的部件,声明指定了这个部件上要设置的属性。例如:QPushButton{color:red}。
在这个样式规则中,QPushButton 是选择器,{ color: red } 是声明。其中,color 是属性,red 是值。
这个规则指定了 QPushButton 和它的子类应该使用红色作为前景色。QT 样式表中一般不区分大小写,例如: color,Color,COLOR 和 COloR 表示相同的属性。只有类名,对象名和 QT 属性名是区分大小写的。一些选择器可以指定相同的声明,使用逗号隔开,例如:QPushButton,QLineEdit,QComboBox{color :red}。
- 为了使用方便,我们还可以使用一种简化形式:
selector1,selector2, ..., selectorM{ attribute1: value1; attribute2: value2;... attoimuteM: xaluaN: }
- 这种简化模式可以同时为与 M 个选择器相匹配的部件设置 N 种属性。例如:
QCheckBox,QComboBox,QSpinBox{ color: red; background-color: wh1te; font: bold; }
- 这个规则设置了所有的 QCheckBox 、QComboBox 和 QSpinBox 的前景色、背景色和字体。
1.2 实际演示
- 在 ui 界面当中,放置一个 Label 标签。
- 可以直接规定具体颜色,即 red,yellow,blue 等等,也可以使用 RGB(R、G、B 都是在 0 到 255 之间) 配对颜色。
- 下面两种都进行展示。
背景色,前景色什么的同理,在此不过多叙述。
2. QT 盒子模型
当使用样式表时,每一个部件都被看作拥有 4 个同心矩形的盒子,如下图所示这 4 个矩形分别是内容 ( content ) ,填衬 ( padding ) ,边框 ( border ) 和边距 ( margin ) 。边距、边框宽度和填衬等属性的默认值都是 0 ,这样 4 个矩形恰好重合。
可以使用 background-image 属性来为部件指定一个背景。默认的,background-image 只在边框以内的区域进行绘制,这个可以使用 background-clip 属性来更改。还可以使用 background-repeat 和 background-origin 来控制背景图片的重复方式以及原点。
一个 background-image 无法随着部件的大小自动缩放,如果想要背景随着部件大小变化,那就必须使用 border-image 。如果同时指定了 background-image 和 borimage ,那么 border-image 会绘制在 background-image 上。
此外,image 属性可以用来在 border-image 上绘制一个图片。如果使用 image 指定的图片大小与部件的大小不匹配,那么它不会平铺或者拉伸。图片的对齐方式可以使用 image-position 属性来设置。
3. 子控件
- 对于一些复杂的部件修改样式,可能需要访问它们的子控件,比如 QComboBox 的下拉按钮,还有 QSpinBox 的向上和向下箭头等。选择器可以包含子控件来对部件的特定子控件应用规则,例如:
QComboxBox::drop-down{image:url(dropdown.png)}
这样的规则可以改变所有 QComboBox 部件的下拉按钮的样式。Qt Style SheetsReference关键字对应帮助文档的 List of Stylable Widgets 一项中列出了所有可以使用的样式表来自定义样式的 Qt 部件,List of SubControls 一项中列出了所有可用的子控件。
4. 伪状态
- 选择器可以包含伪状态来限制规则在部件的指定状态上应用。伪状态出现在选择器之后,用冒号隔离,例如:
QPushButton:hover{color:white}
这个规则表明当鼠标悬停在一个 QPushButton 部件上时才被应用。伪状态可以使用感叹号来表示否定。例如,要当鼠标没有悬停在一个 QRadioButton 上时才应用规则,那么这个规则可以写为:
这个规则表明当鼠标悬停在一个 QPushButton 部件上时才被应用。伪状态可以使用感叹号来表示否定。例如,要当鼠标没有悬停在一个 QRadioButton 上时才应用规则,那么这个规则可以写为:
- 伪状态还可以多个连用,达到逻辑与效果。例如,当鼠标悬停在一个被选中的 QCheckBox 部件上时才应用规则,那么这个规则可以写为:
QCheckBox: hover:checked{color:white}
- 如果有需要,也可以使用逗号来表示逻辑或操作,例如:
QCheckBox : hover,QCheckBox;checked{color :white) • 1
- 当然,伪状态也可以和子控件联合使用:
QComboBox :: drop- down: hover { image;url(dropdown_bright.png)}
Qt Style Sheets Reference 关键字对应帮助文档的 List of Pseudo-States 一项中列出了 Qt 支持的所有伪状态。
5. 冲突解决
- 当几个样式规则对相同的属性指定了不同的值时就会产生冲突。例如:
QPushButton# okButton(color:gray} QPushButton {color:red}
这样,okButton 的 color 属性便产生了冲突。
解决这个冲突的原则是:
(1) 特殊的选择器优先。 因为 QPushButton# okButton 一般代表一个单一的对象,而不是一个类所有的实例,所以它比 QPushButton 更特殊,那么这时便会使用第一个规则,okButton 的文本颜色为灰色。
(2) 有伪状态比没有伪状态优先。如果两个选择符的特殊性相同,则后面出现的比前面的优先。Qt 样式表使用 CSS2 规范来确定规则的特殊性。
6. 选择器类型
- Qt 样式表支持 css2 中的所有选择器。表中列出常用的选择器类型: