文章目录
- window frame属性
- window frame的概念
- 1. window frame的影响
- 2. 图片演示
- 3. 代码演示
- API接口
- widget.cpp(测试代码)
- windowTitle属性
- API接口
- 问题 + 注意点
- widget.cpp(属性用法)
- windowIcon属性
- API接口
- 啥是窗口图标
- 玩法
- 1. 先看代码 + 效果图
- 2. icon传参问题(特别注意)
- qrc机制(重点)
- 绝对路径与相对路径
- 啥是qrc机制 + 解决的问题
- 具体操作流程
window frame属性
window frame的概念
1. window frame的影响
- 如果
widget
作为⼀个窗⼝ (带有标题栏, 最⼩化, 最⼤化, 关闭按钮), 那么在计算尺⼨和坐标的时候就有两种算法,看是否包含window frame
和 不包含window frame
这两种类型 - 其中
x(), y(), frameGeometry(), pos(), move()
都是按照包含window frame
的⽅式来计算的 - 其中
geometry(), width(), height(), rect(), size()
则是按照不包含window frame
的⽅式来计算的 - 当然, 如果⼀个不是作为窗⼝的 widget , 上述两类⽅式得到的结果是⼀致的.
2. 图片演示
- 可以通过一些特殊的API接口把
window frame
窗口框架(该操作系统自带的
)给隐藏掉,比如说一些游戏的运行窗口界面的窗口框架就可以隐藏
3. 代码演示
- 问题一:下面打印出来的两个坐标不是一样的吗?这是怎么回事。咱们在此处是直接针对
widget
对象来观察区别,而当前代码是放到了构造函数中,此时这个widget
对象正在构造,还没有被加入到window frame
中,因此此时还看不到window frame
的影响
- 问题一的解决方案:直接定义该按钮的槽函数(
转到槽定义
),点击按钮后,再去打印这两者原点的坐标
API接口
API | 说明 |
---|---|
x() | 获取横坐标 |
y() | 获取纵坐标 |
pos() | 返回 QPoint 对象,里面包含 x(), y(), setX(), setY() 等方法 |
frameSize() | 返回 QSize 对象 |
frameGeometry() | 返回 QRect 对象 上面五种(包括这一种)计算时包含 window frame |
width() | 获取宽度 |
height() | 获取高度 |
size() | 返回 QSize 对象,里面包含 width(), height(), setWidth(), setHeight() 等方法 |
rect() | 返回 QRect 对象 |
geometry() | 返回 QRect 对象。QRect 相当于 QPoint 和 QSize 的结合体。可以获取 x, y, width, height |
setGeometry() | 直接设置窗口的位置和尺寸。可以设置 x, y, width, height, 或者 QRect 对象。 上面六种(包括这一种)计算时不包含 window frame 对象 |
- 认真观察上⾯的表格, 可以看到, 其实这⾥的 API 有
frameGeometry
和geometry
两个就⾜够完成所有的需求了。为什么要提供这么多功能重复的 API 呢? - 这个就涉及到 Qt API 的设计理念了: 尽量符合⼈的直觉。举个例子,Qt 的
QVector
的尾插元素操作,有方法:push_back,append,+=
,上述⽅法的效果都是等价的,即使不翻阅⽂档, 单纯的凭借直觉就能把代码写对。
widget.cpp(测试代码)
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
// QRect rect1 = this->geometry();
// QRect rect2 = this->frameGeometry();// // 打印这两的原点坐标 + 宽度与高度
// qDebug() << rect1;
// qDebug() << rect2;
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();// 打印这两的原点坐标 + 宽度与高度qDebug() << rect1;qDebug() << rect2;
}
windowTitle属性
API接口
API | 说明 |
---|---|
windowTitle() | 获取到控件的窗口标题 |
setWindowTitle(const QString& title) | 设置控件的窗口标题,传参支持隐式类型转换,直接传字符串即可 |
问题 + 注意点
- 问题二的原因:当前的
windowTitle(窗口标题)
属性是从属于QWidget
的,QWidget
是一个广泛的概念,而该属性只能针对顶层窗口这样的QWidget
才有效 - 注意点:当前不应该给按钮设置
windowsTitle
,但是实际设置之后,没有任何效果,也没有报错,但此时没有报错
它这样的设定是不科学的,关于这一点,咱们更希望当代码写出不科学的代码的时候,能够给一些报错提示
widget.cpp(属性用法)
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("这是窗口标题");
}
windowIcon属性
API接口
API | 说明 |
---|---|
windowIcon | 获取到控件的窗口标题,返回QIcon 对象 |
setWindowIcon(const QIcon& icon) | 设置控件的窗口图标 |
同windowTitle,上述操作仅针对顶层
widget
有效
啥是窗口图标
- 先来说一下这个
QIcon
对象,Qt把各种涉及到的相关概念都封装成了类,而QIcon就表示一个图标
玩法
1. 先看代码 + 效果图
代码虽然简单,但牵扯到的东西却不这么点,
特别注意路径和图片文件名别带中文,别带中文!!!带了后,一堆麻烦事,下面的代码虽然能成功,但有隐患,坑留在了具体操作流程的最后一步
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 设置图标--要包含头文件(头文件就是类名)--文件名别带中文QIcon icon("C:/Users/dx156/Pictures/微信图片_20250418202557.jpg");this->setWindowIcon(icon);
}
2. icon传参问题(特别注意)
- 传参传的是本地图片的路径,该路径最好不要带有中文!!!我上面的中文是文件名,
C:\Users\dx156\桌面\solidworks.png
(传入此参数,这种写法带有中文路径) - 这里咱们得使用
/
作为路径之间的分隔符,也就是上面代码的写法,不可使用\
反斜杠作为分隔符,因为它会作为转义字符,比如\r
这两字符就被视为是一个字符(回车符
)- 因此为了解决这个问题,除了用
/
作为路径之间的分隔符外,C++11中引入了raw string(原始字符串)
去解决上述问题,即字符串里不包含任何转义字符(所有的字符都不会转义) - 当然针对转义字符还可以使用双双反斜杠
\\
- 因此为了解决这个问题,除了用
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 设置图标--要包含头文件(头文件就是类名)QString text = R"(C:\Users\dx156\Pictures\微信图片_20250418202557.jpg)";QIcon icon(text);this->setWindowIcon(icon);
}
- 这里的
QIcon
对象是在栈上创建,之前推荐使用堆来创建对象,主要是因为要确保当前的控件的生命周期是足够的,且要通过Qt对象树来释放对象,而Qlcon
自身是一个比较小的对象,创建出来之后,就是要设置到某个QWidget
里面,而且Qlcon
对象本身释放不释放,不影响图标最终的显示,另外lcon也不支持对象树,无法给他执行父对象
qrc机制(重点)
绝对路径与相对路径
- 绝对路径的问题:上述代码传参传的该图片的地址是
绝对路径
,通过绝对路径的方式引入图片是不科学的,毕竟你写的程序最终是要发布到用户的电脑上的,那你无法确保,你开发机上图片的路径和用户电脑上图片的路径完全一致,比如咱们这个电脑是把图片放到D盘上,那有可能用户电脑上只有一个C盘没有D盘咋办 - 因此相比于使用绝对路径的方式,使用相对路径是更好的
- 相对路径,是以给定目录为基准,以
.
或者..
的方式开头 - 假设基准目录是
D:/
,给定相对路径:./rose.jpg
→在基准目录 (D:/
)直接找rose.jpg
,给定的相对路径是./image/rose.jpg
→ 在基准目录中,先找到image
目录,再在里面找到rose.jpg
- 这个
..
就是到上一级路径中去找,.
就是到当前在哪个各路径(基准路径)就从哪个路径开始找
- 相对路径,是以给定目录为基准,以
- 相对路径的问题:以相对路径的形式引入图片,把图片和可执行程序放在一个相对合适的位置,比绝对路径这种方式更好一点。不过要把图片和可执行程序以相对路径这个文件一起打包发给用户,但也无法确保这个文件不会被用户搞丢
啥是qrc机制 + 解决的问题
- qrc 机制就是从根本上解决上述的两个问题
- 确保你的图片所在的路径在目标用户机器上存在
- 确保你的图片不会被用户搞没了
- 给 Qt 项目引入一个额外的xml 文件(后缀名使用
.qrc
表示)在这个 xml 中把要使用的图片资源给导入进来,并且在xml中进行记录。Qt在编译项目的时候,就会根据qrc
中描述的图片信息,找到图片内容,并且提取出图片的二进制数据,把这些二进制数据转成C++代码,最终编译到exe里。 - qrc 缺点:无法导入太大的资源文件,比如搞几个 GB这种视频文件,qrc 无能为力了
具体操作流程
-
在项目中创建一个
qrc
文件,文件名不要带中文和特殊符号,直接下一步,下一步
-
来到这个界面后,点击
Add Prefix
把图片导入到qrc
中
-
先创建一个前缀(
Prefix
),把Prefix
的名字改成/
即可
- 所谓的
前缀
可以理解成虚拟的目录,这个目录没有在你的电脑上真实存在,是Qt 自己抽象出来的。qrc 机制本质上就是把图片的二进制数据转成C++代码(最终就会在代码中看到很大的char数组,里面就是图片的二进制数据),那为了方便 Qt 代码中访问到这个图片,Qt 就自己抽象出了 虚拟的目录 - 下面的文件是要完整操作了整个流程才会生成的,放在这里是为了辅助理解上面的话语。那
qrc
中导入的图片资源就会被转成这个qrc_resource_cpp
这个C++代码,下面的字节内容就是图片文件(.jpg
)里每个字节的数据,当Qt项目进行编译的时候,这个cpp文件就被一起编译到了exe中,当exe程序运行的时候,上述图片的数据也被加载到内存中(这是qrc机制工作的本质所在)
- 所谓的
-
把你要使用的图片给导入到资源文件中。这个按钮在创建
prefix
之前是禁用的,创建好prefix
之后就可以使用了,添加的文件就是添加到prefix
下面的
-
进行上一步之后,会出现如下问题。因为点击
Add Files
得到的目录就是当前代码所在的目录
-
将你的图片拷贝到当前项目目录中即可。鼠标放在
widget.cpp
文件上,右键点击选择在Explorer中显示
,将图片拷贝到此目录
-
重复第四步。看到下面的这个效果就说明导入成功了
-
创建的前缀叫啥名字,代码中写啥名字。当代码中需要访问
qrc
中管理的文件时,就需要在路径上带有:: + 前缀名+ 文件名
。我这里最终还是遭了殃:文件名也不能是中文的,.jpg前一堆问号
,先把该文件名给改了,然后鼠标右键resource.qrc
打开Open in Editor
重新删除添加文件
#include "widget.h"
#include "ui_widget.h"
#include<QIcon>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QIcon icon(":/image.jpg");this->setWindowIcon(icon);
}Widget::~Widget()
{delete ui;
}