目录
一、概述
二、Qwidget常用属性及函数介绍
2.1 enable
2.2 geometry
2.3 windowTitle
2.4 windowIcon
2.5 cursor
2.6 font 设置字体样式
2.7 toolTip
2.8 focusPolicy焦点策略
2.9 styleSheet
一、概述
widget翻译而来就是小控件,小部件。控件是指可以操纵的部件,下图Qt页面中的按钮, 列表视图, 树形视图, 单⾏输⼊框, 多⾏输⼊框, 滚动条, 下拉框等, 都可以称为 "控件".
QWidget是所有窗口部件的基类,例如对话框类、主窗体类,以及其他诸如按钮、编辑框、标签等都由QWidget派生得到,所以QWidget的所有的方法往往都可以在其他子类当中使用
二、QWidget核心属性
属性 | 作用 |
enable | 设置控件是否可用,true表示可用,false表示不可用 |
geometry | 位置和尺寸,包含x,y,width,height四个部分 |
windowTitle | 设置widget标题 |
windowIcon | 设置widget图标 |
windowOpacity | 设置widget透明度 |
cursor | 鼠标悬停时显示的图标形状,是普通箭头,还是沙漏等选项,也可以自定义图标 |
font | 字体相关属性,涉及到字体家族,字体大小,粗体,斜体,下划线等样式 |
toolTip | 鼠标悬停在widget上会在状态栏中显示的提示信息 |
toolTipDuring | toolTip显示的持续时间 |
statusTip | Widget状态发生改变时显示的提示信息(比如按钮被按下等) |
whatsThis | 鼠标悬停并按下alt+F1时,显示的帮助信息(显示在一个弹出的窗口中) |
styleSheet | 允许使用CSS来设置widget中的样式 |
focusPolicy | 该widget如何获取到焦点 Qt::NoFocus 控件不参与焦点管理,即无法通过键盘或鼠标获取焦点 Qt::TabFocus 控件可以通过Tab按键获得焦点 Qt::ClickFocus 控件可以通过鼠标点击获得焦点 QT::StrongFocus 空间可以通过鼠标和键盘Tab任意一个来获得焦点 Qt::WheelFocus 控件可以通过鼠标滚轮来获得焦点 |
contextMenuPolicy | 上下文菜单显示策略 Qt::DefaultContextMenu 默认的上下文菜单策略,用户可以通过鼠标右键或键盘快捷键触发上下文菜单 Qt::NoContextMenu 禁用上下文菜单,即使用户点击鼠标右键也不会显示菜单 Qt::PreventContextMenu 防止控件显示上下文菜单,即使用户点击鼠标右键也不会显示菜单 Qt::ActionsContextMenu 将上下文菜单替换控件的动作菜单,用户可以通过鼠标右键或者键盘快捷键触发这个菜单 Qt::CustomContextMenu 使用自定义的上下文菜单,用户可以通过鼠标右键或键盘快捷键来触发这个菜单 |
locale | 设置语言和国家地区 |
acceptDrops | 该部件是否接受拖放操作 如果设置为true,那么该部件就可以接收来自其他部件的拖放操作。当一个部件被拖放到该部件上时,该部件会接收到相应的拖放事件(如dropEvent) |
minimumSize | 控件的最小尺寸,包含最小宽度和最小高度 |
maxmumSize | 控件的最大尺寸,包含最大宽度和最大高度 |
sizePolicy | 尺寸策略,设置控件在布局管理器中的缩放方式 |
windowModality | 指定窗口是否具有模态行为 |
sizeIncrement | 拖动窗口大小时的增量单位 |
baseSize | 窗口的基础大小,用来搭配sizeIcrement调整组件尺寸是计算组件应该调整到的合适的值 |
palette | 调色板,可以设置widget的颜色风格 |
mouseTracking | 是否要跟踪鼠标的移动事件 如果设置为true,表示需要跟踪,则鼠标划过的时候该widget就能持续收到鼠标移动的事件 如果设置为true,表示不需要跟踪,则鼠标划过的时候该widget就不能持续收到鼠标移动的事件 |
tableTracking | 是否跟踪触摸屏的移动事件 类似于mouseTracking,Qt 5.9 中引入的新属性 |
layoutDirection | 布局方向 Qt::LeftToRight 文本从左到右排列,也是默认值 Qt::RightToLeft 文本从右往左排列 Qt::GlobalAtomics 部件的布局方向由全局原子性决定(根据应用程序中的其他widget布局方向确定的) |
autoFillBackground | 是否自动填充背景颜色 |
windowFilePath | 能够把widget和一个本地文件路径关联起来 |
accessibleName | 设置widget的可访问名称,可以被辅助技术获取到,用于实现无障碍程序的场景中(为视力障碍人群写的程序) |
accessibleDescription | 设置widget的详细描述,作用同accessibleName |
inputMethodHints | 针对输入框有效,用来提示用户当前能输入的合法数据的格式,比如只能输入数字,只能输入日期等 |
二、Qwidget常用属性及函数介绍
2.1 enable
enable属性是指这个控件是否可用,有两个常用的函数。isEnable()获取到控件的可用状态,setEnabled设置控件是否可用,true表示可用,false表示不可用
例子1 使用代码创建一个禁用状态的按钮
例子2 通过按钮2切换按钮1的禁用状态
也可以进一步把按钮2改一下,先获取按钮1的可用状态,如果按钮1不可用就设置成可用,如果可用就把点击按钮2设置成点击了后按钮1就切换成禁用状态
2.2 geometry
geometry是描述控件位置和宽高的属性,内部有四个成员,x横坐标,y纵坐标,width宽度,height高度
x,y的计算不是和以往数学里的笛卡尔坐标系一样,原点在中心,第一象限在右上
geometry的x,y是以左上角为原点,只考虑第一象限(也就是只考虑x,y都为正的情况)
举个例子,控件的x,y,width,height示意图
geometry常用的函数
函数 | 说明 |
geometry | 获取到控件的位置和尺寸,返回结果是一个QRect |
setGeometry(QRect) setGeometry(int x,int y,int width,int height) | 设置控件的位置和尺寸,可以直接设置一个QRect,也可以分四个属性单独设置 |
QRect是一个小控件,里面包含了x,y,width,height,这个可以通过qDebug()直接打印出来
举个例子
为什么QRect不用挂对象树上,而QPushButton挂对象树上了呢,这是因为有些小的控件没有占据太大的空间,所以通过生命周期到期直接释放销耗也不会很大。那么怎么分辨哪些是需要挂对象树上的,哪些是不要的呢,QPoint和QRect这些数据处理,不是可视的控件,就不用挂对象树上了,QPushButton,QLabel这些肉眼可见,运行了也可见的控件就得挂对象树。还有一种情况需要考虑,如果一个控件是栈上实例化的,而此时需要set或者add到一个父容器上,此时也相当于挂到对象树上了,此时就得考虑一种情况:如果它是在函数里实例化的,那么出来函数作用域就直接销毁了,但是此时它还挂在父控件的对象树上,此时就有风险。
例子2 编写四个按钮,控制目标进行上下左右移动
#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton *target=new QPushButton("我是目标",this);
target->setFixedSize(200,100);//设置控件固定大小,宽为200,高为100
target->move(250,200);
QPushButton *btnleft=new QPushButton("左移",this);
btnleft->move(250,400);
connect(btnleft,&QPushButton::clicked,target,[=](){
QRect rect=target->geometry();
target->setGeometry(rect.x()-5,rect.y(),rect.width(),rect.height());
});
QPushButton *btnright=new QPushButton("右移",this);
btnright->move(350,400);
connect(btnright,&QPushButton::clicked,target,[=](){
QRect rect=target->geometry();
target->setGeometry(rect.x()+5,rect.y(),rect.width(),rect.height());
});
QPushButton *btnup=new QPushButton("上移",this);
btnup->move(300,350);
connect(btnup,&QPushButton::clicked,target,[=](){
QRect rect=target->geometry();
target->setGeometry(rect.x(),rect.y()-5,rect.width(),rect.height());
});
QPushButton *btndown=new QPushButton("下移",this);
btndown->move(300,450);
connect(btndown,&QPushButton::clicked,target,[=](){
QRect rect=target->geometry();
target->setGeometry(rect.x(),rect.y()+5,rect.width(),rect.height());
});
frameGeometry也是描述控件位置和宽高的属性,内部也是一样的,包含x横坐标,y纵坐标,width宽度,height高度 。
区别在于前者不计算frame,后者会加上frame来进行计算,一个完整的窗口是包含标题栏,最小化,最大化和关闭按钮的,后者会把这些表示状态以及菜单工具栏一块加入计算
拿wps来举个例
如果是frameGeometry,它会连带上面的菜单栏和左侧的侧边栏一块计算了
如果是geometry,那么它的x和y就不会计算frame的东西
可以分别用QRect取geometry和frameGeometry来打印看看差距
为什么上图中的结果一样呢,这是因为此时是在窗口的构造函数里进行计算,此时widget还没完全构造出来呢(构造函数完了才是完全构造出来了),所以可以通过按钮槽函数来查看结果。槽函数和构造函数具有异步性,它要保证所有控件都构建完了才会去触发槽函数的信号。
2.3 windowTitle
windowTitle就是窗口标题,但是这个只对顶层widget(独立窗口)有效,对子控件和子窗口无效
相关函数
函数 | 说明 |
windowTitle | 获取到控件的窗口标题 |
setWindowTitle(const QString& title) | 设置控件的窗口标题 |
例子
2.4 windowIcon
windowIcon是设置窗口图标,与上面的标题类似,都只能用到顶层窗口
函数 | 说明 |
windowIcon | 获取到控件的窗口图标,返回QIcon对象 |
setWindowIcon(const QIcon& icon) | 设置控件的窗口图标 |
QIcon是Qt中专门表示图标的类,可以从多种来源加载图标,包括文件(如PNG、SVG、JPEG等格式)
常见的QIcon构造函数有两种,通过QPixmap来构造QIcon,QPixmap是图像类,另一种就是直接传文件路径来构造QIcon
设置图标例子
绝对路径设置图标,windows的默认路径可能会有\,比如E:\edge\jijj 但是一般都识别不出来,因为转义字符也会用 \ 这个符号,所以一般写路径要么写成 E:\\edge\\jijj 要么就写成E:/edge/jijj
相对路径设置图标
相对路径是相对当前程序工作目录的路径的路径,比如我当前工作目录是E:\Qt\q\content\widget_geometry\Debug},那么如果把图片复制到这个路径下,可以直接写图片名称进行访问。
对于相对路径,./是指当前目录,而../是上一级目录
但是通过相对路径和绝对路径都容易找不到路径或路径出错,最好的办法就是图片和代码放到一块去,这样即使修改了工作目录或者把图片删除了都可以找到相关的图片。Qt使用qrc机制来帮我们自动完成了上述工作,更方便管理项目依赖的静态资源。
qrc文件是一种XML格式的资源配置文件,它用XML记录硬盘上的文件和对应的随意指定的资源名称,应用程序通过资源名称来访问这些资源。实际上Qt会对XML语句进行解析,然后形成对应的C++代码,这就是元编程的一种,用代码生成代码
在构建程序的过程中,Qt会把资源文件的二进制数据转成CPP代码,编译到exe中,从而使依赖的资源变得“路径无关”
例子如下
首先把要进行处理的文件复制到.pro配置文件的相同目录当中,这个路径不一定就是当前工作目录
然后Qt中新建Qt资源文件
然后添加前缀,这个前缀是模拟文件路径,如果你加了前缀,那么在使用资源的时候就也得加上这个前缀。也可以不添加前缀,直接/
然后添加文件,把事先准备好的的图片添加进来
编写代码
在这个代码中一定要在最开头加上冒号:,这样它才知道要去qrc当中找资源。/就是直接添加的前缀,如果你加了别的前缀,比如res,那么这个路径就得写成":/res/mm.png";
但是如果此时你把原来文件夹里的图片删除了,然后再回到编译器中进行编译运行,就会报错:-1: error: No rule to make target '../untitled20/mm.png', needed by 'debug/qrc_res.cpp'. Stop. 这是因为虽然它已经编译进exe文件中了,但是每次编译都会重新指向上面的把图片编进exe文件当中的步骤,每次都得到那个路径去找图片,所以你把它删了然后再编译就会报错。但是程序到最后打包完成软件,此时丢失了原图片路径就没什么关系,因为exe文件当中已经有图片的二进制数据了,所以丢失了也没关系
可以在debug文件夹当中看到此时生成了qrc_res.cpp文件,打开可以看到这个文件里面其实就是一个巨长的字符数组,这个数组就是把图片拆解成二进制数据的数组
上述 qrc 这⼀套资源管理⽅案, 优点和缺点都很明显.优点: 确保了图⽚, 字体, 声⾳等资源能够真正做到 "⽬录⽆关", ⽆论如何最后打包完软件都不会出现资源丢失的情况.缺点: 不适合管理体积⼤的资源. 如果资源⽐较⼤ (⽐如是⼏个 MB 的⽂件), 或者资源特别多,⽣成的最终的 exe 体积就会⽐较⼤, 程序运⾏消耗的内存也会增⼤, 程序编译的时间也会显著增加
2.5 windowOpacity不透明度
实际上是透明度,因为一开始默认的就是最高的不透明度,只能往下调整到不透明
API | 说明 |
windowOpacity | 获取到控件的不透明值,返回float,取值为0.0->1.0,其中0.0表示全透明,1.0表示完全不透明。默认是1.0 |
setWindowOpacity(float n) | 设置控件的不透明数值 |
例子 通过按钮来加减窗口的不透明度
从输入框可以看出不透明度的加减并不是精确地加减0.1,这是因为C++中float严格遵守IEEE754标准,因此在进行运算的时候会有一定的精度误差,因此1加减0.1的数值不是精确的0.1
2.5 cursor
设置鼠标的图案
API | 说明 |
cursor() | 获取到当前widget的cursor属性,返回QCursor对象,当鼠标悬停在该widget上时,就会显示出对应的形状 |
setCursor(const QCursor&cursor) | 设置该widget光标的形状,仅在鼠标停留在该widget上时生效 |
QGuiApplication::setOverrideCursor(const QCursor& cursor) | 设置全局光标的形状,对整个程序中的所有widget都会生效,覆盖上面的setCursor设置的内容 |
例子 设置鼠标进入按钮区域的图案为十字
Qt中枚举了一些鼠标的图案
- ArrowCursor: 标准箭头光标,通常用于表示可点击的区域。
- UpArrowCursor: 向上箭头光标,通常用于表示文本选择或移动。
- CrossCursor: 十字光标,通常用于绘图或选择区域。
- WaitCursor: 等待光标,通常用于表示程序正在处理某些操作(例如加载)。
- IBeamCursor: I型光标,通常用于文本输入区域,表示可以选择和编辑文本。
- SizeVerCursor: 垂直调整大小光标,通常用于上下调整窗口或区域的大小。
- SizeHorCursor: 水平调整大小光标,通常用于左右调整窗口或区域的大小。
- SizeBDiagCursor: 从左上到右下的对角线调整大小光标,通常用于对角线方向的调整大小。
- SizeFDiagCursor: 从右上到左下的对角线调整大小光标,通常用于对角线方向的调整大小。
- SizeAllCursor: 四向调整大小光标,通常用于表示可以在四个方向上移动或调整。
- BlankCursor: 空光标,通常用于不表示任何指针的场景。
- SplitVCursor: 垂直分割光标,通常用于表示需要进行垂直分割的操作。
- SplitHCursor: 水平分割光标,通常用于表示需要进行水平分割的操作。
- PointingHandCursor: 指向手光标,通常用于表示链接或可点击区域。
- ForbiddenCursor: 禁止光标,通常表示当前操作不被允许或不可用。
- WhatsThisCursor: "What's This"光标,通常用于帮助提示或解释。
- BusyCursor: 忙碌光标,通常用于表示当前正在进行某些操作。
- OpenHandCursor: 开手光标,通常用于表示可以移动物体。
- ClosedHandCursor: 闭手光标,通常用于表示可以抓取物体。
- DragCopyCursor: 拖拽复制光标,通常用于表示在移动内容的同时进行复制。
- DragMoveCursor: 拖拽移动光标,通常用于表示移动物体而不是复制。
- DragLinkCursor: 拖拽链接光标,通常用于表示将内容作为链接释放。
- LastCursor: 最后一个光标类型,表示拖拽链接光标(
DragLinkCursor
)的枚举值。 - BitmapCursor: 位图光标,通常用于用户自定义的位图光标。
- CustomCursor: 自定义光标,通常可以通过程序代码定义的光标样式
例子2 自定义鼠标图案
自定义鼠标图案,需要用Pixmap图像类,QCursor支持Pixmap构造,所以可以借助Pixmap完成自定义鼠标图案
2.6 font 设置字体样式
APi | 说明 |
font() | 获取当前widget的字体信息,返回QFont对象 |
setFont(const QFont&font) | 设置当前widget的字体信息 |
QFont的相关属性
属性 | 说明 |
family | 字体家族,比如 “楷体”,“宋体”,“微软雅黑”等 |
pointSize | 字体大小 |
weight | 字体粗细,以数值方式表示粗细程度取值范围为[0,99],数值越大,越粗 |
bold | 是否加粗,设置为true,相当于weight为75,设置为false相当于weight为50 |
italic | 是否倾斜 |
underline | 是否带有下划线 |
strikeOut | 是否带有删除线 |
例子 设置Label 标签的字体
未设置font属性的样式
设置了font属性的文本样式
2.7 toolTip
显示提示信息
API | 说明 |
setToolTip | 设置toolTip 鼠标悬停在该widget上时会有提示说明 |
setToolTipDuring | 设置toolTip提示的时间,单位ms 时间到后tooltip自动消失 |
setToolTipDuring不设置这个的话你放上去提示信息会一直存在,单位是ms毫秒,1000毫秒等于1秒,1000秒等于1微秒
2.8 focusPolicy焦点策略
设置控价获取到焦点的策略,比如某个控件能否用鼠标选中或者能否通过tab键选中
所谓"焦点",指的是能选中这个元素,接下来的操作(比如键盘操作),就都是针对该焦点元素进行的了,这个对于输入框,单选框,复选框等控价非常有用
比如说打开浏览器,你不点搜索框直接按键盘打字,搜索框是没有字呈现的,必须先用鼠标点击了搜索框,然后键盘输入文字搜索框才有反应。搜索框不点它就无法输入文字,这就是没获取到焦点。
API | 说明 |
focusPoilcy() | 获取该widget的focusPolicy,返回Qt::FocusPolicy |
setFocusPolicy(Qt::FocusPolicy policy) | 设置widget的focusPolicy |
Qt::FocusPolicy是一个枚举类型,取值如下
-
NoFocus (0):
- 窗口部件不接受焦点。用户无法通过键盘(如 Tab 键)或鼠标单击使其获得焦点。
-
TabFocus (0x1):
- 窗口部件可以通过 Tab 键获得焦点。用户在按 Tab 键时,能够将焦点移到此部件。
-
ClickFocus (0x2):
- 窗口部件可以通过鼠标单击获得焦点。当用户单击该部件时,它会获得焦点。
-
StrongFocus (TabFocus | ClickFocus | 0x8):
- 窗口部件可以同时通过 Tab 键和鼠标单击获得焦点。plus 0x8 表示它可能有额外的行为(比如支持更复杂的焦点管理)。这是一个更强的焦点策略,它确保该部件具备获取焦点的多种方式。
-
WheelFocus (StrongFocus | 0x4):
- 窗口部件支持强焦点,并且还能够通过滚轮事件获得焦点。当用户滚动鼠标滚轮时,该部件将获得焦点。这个选项通常用于需要滚动输入的窗口部件,例如列表框或文本框。
例子 两个输入框通过tab键和鼠标来切换焦点
2.9 styleSheet
通过css设置widget的样式
css层叠样式表(Cascading Style Sheets层叠样式表)本身属于网页前端技术,主要就是用来描述界面的样式
所谓“样式”,包括不限于大小,位置,颜色,间距,字体,背景,边框等
我们平时看到的丰富多彩的网页,就都会用到大量的css
Qt虽然是做GUI开发,但实际上和网页前端有很多异曲同工之处,因此Qt也引入了对于CSS的支持
CSS中可以设置的样式属性非常多,基于这些属性Qt只能支持其中的一部分,称为QSS(Qt Style Sheet)具体的支持情况可以参考Qt文档中“Qt Style Sheets Reference”章节
例子通过styleSheet 样式表设置Label的文字样式
也可以通过Qt Designer的ui设置来实现上面的所有属性的例子,上面的例子基本上都是使用纯代码的方式实现
拖拽Line Edit控件到工作界面
先选中Line Edit输入框,然后右键改变样式表
在样式表里直接输入之前代码当中stylesheet的样式,先点击应用然后才是确定
例子2 通过按钮来切换窗口的日间模式和夜间模式
先通过ui界面拖拽出基本的页面出来
因为要通过点击来改变界面颜色,所以需要用到信号和槽,有两种写法
第一种写法还是和之前一样直接connect联系起来信号和槽
那么我怎么访问到ui界面中的按钮呢,重新再new一个按钮出来吗,其实不是的,ui界面其实相当于是一个类指针,所以可以直接通过ui-> 来访问这个类的元素
从widget构造函数里也可以看到这个ui类被设置成了widget的成员变量
然后connect的代码和之前都差不多
第二种做法是回到ui界面选中按钮,右键转到槽,选择clicked信号
然后就会自动回到.cpp文件当中,此时会自动生成了一个槽函数void Widget::on_pushButton_clicked()
如法炮制把connect里的代码复制下来
也完成了同样的功能
为什么转到槽自动形成一个槽函数,并且不用写connect就可以实现connect相同的功能呢。
在qrc那里说过qrc的东西会通过XML的描述性的代码生成qrc_res.cpp文件,用代码生成代码,符合元编程思想。ui界面也是通过上述操作来自动生成代码的
仔细看配置文件的话是会发现,有一个widget.ui的文件,打开可以看到里面全是XML语句
Qt会通过这个.ui文件生成一个ui_widget.h文件
打开这个文件,其实可以看到它也new了一系列东西出来,比如Push_Button按钮或者LineEdit
那么它是怎么实现connect呢, QMetaObject::connectSlotsByName
隐式地实现了信号和槽的连接。
1.当 QPushButton 被点击时,QPushButton::clicked() 信号就会被发出2.QMetaObject::connectSlotsByName 函数会查找对应的槽函数(例如 on_pushButton_2_clicked())并将这两个进行连接。
最后一个问题在于就是我点击运行的时候
原界面是这样的
原界面大背景明显是带点灰色的,但是点完夜间模式再点日间模式切换回来就变成纯白的了
所以在日间模式里把this的背景色改成接近灰色,把LineEdit单独改成白色,但是这样就涉及到了一个问题,background-color:black;我这样是直接填黑色,这种直接描述颜色的单词,但是更多颜色可不一定都有单词相对应。其实一般填充颜色都是按照rgb(255,255,255);这之类的填写的, 按照计算机三原色红绿蓝占比来控制相对应的颜色。也可以写成background-color:#FFFFFF;前两个F是指红色占比满了,中间是绿色占比,最后两个是蓝色占比
所以如果想获取精确的背景颜色可以使用rgb表示颜色,用取色器根据来获取颜色,修改如下