文章目录
- 前言:
- 1. windowTitle: 窗口标题
- 2. windowIcon:窗口图标
- 3. qrc 机制:
- 4. windowOpacity:半透明效果
- 总结:
前言:
在软件开发中,用户界面(UI)的构建是一个重要环节,它直接影响到用户的使用体验。Qt作为一个跨平台的C++应用程序框架,提供了丰富的工具和类库来帮助开发者创建和管理复杂的用户界面。本文将详细介绍Qt中窗口标题、窗口图标、资源文件(qrc机制)以及窗口透明度等UI元素的设置和使用。通过这些基础知识的掌握,开发者可以更高效地构建出既美观又实用的应用程序界面。
1. windowTitle: 窗口标题
当前 windowTitle
属性,是从属于 QWidget
, 但QWidget
是一个广泛的概念。
windowTitle
属性,只能针对顶层窗口这样的QWidget
才有效。
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("这是窗口标题");
QPushButton* button = new QPushButton(this);
button->setText("按钮");
// button->setWindowTitle("通过按钮设置窗口标题"); // 当前不应该给按钮设置 window Title。
// // 但是实际设置了之后,也没有报错,这样的设定是不太科学的
connect(button, &QPushButton::clicked, this, [this](){
this->setWindowTitle("通过按钮设置窗口标题");
});
}
Widget::~Widget()
{
delete ui;
}
2. windowIcon:窗口图标
Qt 把各种涉及到的相关概念,都封装成了类。
QIcon
就表示一个图标。
这两个 API 类似于 windowTile
只能针对顶层窗口使用。
用它需要先准备好图标的图片。
之前推荐使用堆来创建对象,主要是因为要保证当前控件的生命周期是足够的,要通过 Qt 对象来释放对象。
QIcon
自身是一个比较小的对象,创建出来之后,是要设置到某个QWidget
里面,QIcon
对象本身释放不释放,不影响图标的最显示。
QIcon
也不支持对象树,无法给他执 行父对象。
#include "widget.h"
#include "ui_widget.h"
#include <QIcon>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 设置图标
QIcon icon("D:/Acode/class111/Qt/TuBiao.png"); // 在栈上创建
this->setWindowIcon(icon);
}
Widget::~Widget()
{
delete ui;
}
注意:路径不要带中文,使用 / 作为路径之间的分隔,不能使用 , 在C/C++ 中 \ 是转义字符。在C++ 11 中引入了 raw string 解决上述问题。 字符中不包含任何转义字符(所有的字符都不会转义)
r("...")
;
QIcon icon("D:/Acode/class111/Qt/TuBiao.png");
通过这种绝对路径的方式引入图片是不科学的。
你写的程序,最终是要发布发到用户电脑上的。
你无法确保,你开发机的图片的路径和用户电脑上图片的路径 完全一致!
因此,相比于使用绝对路径的方式,使用相对路径是更好的。
相对路径,是以给定目录为基准,以 .
或者..
的方式开头。
3. qrc 机制:
这个机制本质上从根本上解决上述两个问题:
- 确保你的图片所在的路径在目标机器上存在
- 确保你的图片不会被用户搞没了
给 Qt 项目引入一个额外的 xml 文件(后缀名使用.qrc表示)
在这个xml中要把图片资源给导入进来,并且在xml中进行记录。
Qt 在编译的项目的时候,就会根据qrc 中描述的图片信息,找到图片内容,并提取出图片的二进制数据,把这些二进制数据转换成C++ 代码,最终编译到exe里。
qrc 缺点:无法导入太大的资源,比如搞几个GB这种视频,qrc无能为力了。
qrc 使用的方式:
-
在项目中创建一个 qrc 文件,文件名不要带中文和特殊符号。
-
把图标导入到 qrc 文件中
1) 先创建一个"前缀" (Prefix)
所谓的"前缀"可以理解成 虚拟目录
这个目录没有在你的电脑上真实存在,是Qt 自己抽象出来的qrc 机制本质上就是把 图片 的的二进制数据转换成C++代码。(最终就会看到很大的char数组,里面就是图片的二进制数据)
为了方便 Qt 代码访问到这个图片,Qt就自己抽象出了虚拟目录。
把Prefix 的名字就改成 / 即可
2)点击Add Files把刚才使用 TuBiao.png 给这个图片导入到资源文件中
需要注意的是,图片必须和resource.qrc 在同级目录,或同级目录的子目录中。
像这样就导入成功了。
#include "widget.h"
#include "ui_widget.h"
#include <QIcon>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 设置图标
//QIcon icon("D:/Acode/class111/Qt/TuBiao.png"); // 在栈上创建
QIcon icon(":/TuBiao.png"); // 用qrc文件存
this->setWindowIcon(icon);
}
Widget::~Widget()
{
delete ui;
}
当 Qt 项目进行编译的时候, 这个cpp文件就被一起编译到exe中。当exe程序运行的时候,上述图片的数据也被加载到内存中了。
4. windowOpacity:半透明效果
半透明效果(opacity,不透明度,数值越大,越不透明)
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_add_clicked()
{
float opacity = this->windowOpacity();
if (opacity >= 1.0) {
return;
}
opacity += 0.1;
qDebug() << opacity;
this->setWindowOpacity(opacity);
}
void Widget::on_pushButton_sub_clicked()
{
float opacity = this->windowOpacity();
if (opacity <= 0.2) {
return;
}
opacity -= 0.1;
qDebug() << opacity;
this->setWindowOpacity(opacity);
}
两个问题:
- 窗口的不透明度,变化并非是精确的!
我们在C语言中学过,数据在内存中的存储
1)整数在内存中的存储(原码 反码 补码,字节序)
2)浮点数在内存中的存储
在这里是用 IEEE 754 标准的浮点数,二进制科学计数法的方式来表示:
把一个浮点数分成三个部分:
1)符号位
2)有效数字
3)指数部分
使用二进制表示的有效数字:
而这里是小于 0 的小数部分(默认整数部分是 1)
第一个有效数字位表示 0.5
第二个有效数字位表示 0.25
第三个表示 0.125 …
0.1 这样的小数,由于float 和 double 有效数字部分长度有限的,导致无法凑出一个非常接近 0.1 这样的数字。
平时写代码,千万不能把两个浮点数直接使用 “==” 进行比较
eg : 0.1 + 0.2 == false;
正确的写法是,作差,判定差的绝对值小于预期范围
后续工作中编写代码的时候,尤其涉及到一些需要精确计算的场景,算钱,一定要慎重使用 float / double!
- 上述代码中,进行设置之前,先判定了 opacity 的范围,然后再决定是否要设置,这个判定其实可以不写。
float opacity = this->windowOpacity();
if (opacity >= 1.0) {
return;
}
这里加了判断条件,实际上如果不加这样的条件代码也是ok的
超过 1.0 的数字设置不进去(setWindowOpacity
内部也经行了判定)
那为啥还要写呢? 《代码大全》就进行了详细的讨论
“防御性编程”,别人犯错了,不会对咱们自身构成太大的伤害。
很多时候写代码的时候,往往是要把一个大的项目拆分成几个部分/模块,不同的人负责不同的人负责分别完成。模块之间要互相交互,往往模块A提供API(函数,类)给模块B调用。
你在使用别人提供的API来进行调用的时候,你是否要对传入的参数进行检测呢?
比如你要传一个实参,你也不知道这个参数是否是一个NULL
指针。
是否应该在调用函数之前就对这个指针进行判空呢?
代码大全中,给出的结论,要双重判定(double check)
总结:
本文详细介绍了Qt中窗口标题、窗口图标、资源文件(qrc机制)以及窗口透明度的设置方法。首先,我们学习了如何为顶层窗口设置窗口标题,并通过按钮点击事件动态改变窗口标题。接着,探讨了如何为窗口设置图标,包括直接使用QIcon类和利用qrc机制将图标资源嵌入到应用程序中。此外,还讨论了窗口透明度的调整,以及浮点数精度问题对透明度设置的影响。最后,强调了防御性编程的重要性,即在代码中加入适当的检查和判断,以提高程序的健壮性和稳定性。