Qt window frame + windowTitle + windowIcon属性(3)
文章目录
- 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;
}

