前言:
在上一讲《QT 第七讲 --- 控件篇 (二)window系列与qrc机制》中,我们探讨了应用程序窗口(QMainWindow
, QWidget
)的基础结构、窗口标志、状态以及Qt强大的资源管理机制(.qrc
文件),这些都是构建应用框架的核心要素。掌握了窗口的宏观管理后,我们本讲将视角聚焦到构成用户界面的微观单元——控件(Widgets)本身的外观与交互细节上。
本次《QT 第八讲 --- 控件篇 (三)界面系列》将深入讲解如何精细化地定制控件的视觉呈现和用户体验。我们将学习如何控制光标(cursor)在控件上的形态,如何设置控件的字体(font)属性,如何提供即时的信息提示(tooltip),如何管理控件的焦点获取策略(focusPolicy),以及最强大也最灵活的界面美化工具——样式表(stylesheet)。这些知识是打造专业、美观、用户友好的QT界面的关键基石。
目录
前言:
一、curser
演示一:
演示二:
演示三:
二、font
演示一:通过图形化界面的方式来设置。
演示二:通过代码实现我们的目的
三、tooltip
演示:
四、focusPolicy
演示:
五、stylesheet
演示:
六、一个小程序
总结:
一、curser
我们首先明白curser是鼠标,这个控件正是控制我们的鼠标演示的。
我们下面看一下这个控件对应的API。
函数名 | 函数介绍 |
---|---|
cursor() | 获取当前 widget 的 cursor 属性,返回 QCursor 对象,当鼠标悬停在该 widget 上时,会显示对应的形状 |
setCursor(const QCursor& cursor) | 设置该 widget 光标的形状,仅在鼠标停留在该 widget 上时生效 |
QGuiApplication::setOverrideCursor(const QCursor& cursor) | 设置全局光标的形状,对整个程序中的所有 widget 都会生效,覆盖上面的 setCursor 设置的内容 |
但是我们也要明白,前两个函数是Widget 级别的,即同一个界面中,不同的控件可以设置成不同的光标。而最后一个函数是对全局生效的,只是针对的当前的程序。
我们废话少说,直接演示一下使用方式。
代码⽰例: 在 Qt Designer 中设置按钮的光标
其实就是一些枚举的值。
演示一:
1) 在界⾯中创建⼀个按钮.
当然为了代码效果的演示,我们先创建一个按钮,观察鼠标在按钮上的区别,由于按钮这个控件是继承的QWidget,所以我们可以直接在按钮的图形化界面上更改。
2) 直接在右侧属性编辑区修改 cursor 属性为 "等待"
我们直接运行程序看下效果。
下面我们通过API接口去实习这个效果。
演示二:
代码⽰例: 通过代码设置按钮的光标
1) 编写 widget.cpp
其中 Qt::WaitCursor 就是⾃带的沙漏形状的光标.
系统内置的光标形状如下:
Ctrl + 左键 点击 Qt::WaitCursor 跳转到源码即可看到.
下面代码很好理解,我们就不进行讲解了。
代码:
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button=new QPushButton(this);button->setCursor(Qt::WaitCursor);// button->setCursor(QCursor(Qt::WaitCursor));//由于我们选择的鼠标图像时Qt自带的,上面两行代码的效果是一样的。//但是我们下面讲解的自定义的图标,只能使用第二种方案了。button->resize(300,300);button->move(200,200);button->setText("这是一个切换鼠标图片的按钮");}Widget::~Widget()
{delete ui;
}
演示效果:
演示三:
Qt允许我们通过自定义的图片来设置光标,先准备一个图片,把图导入到项目中(qrc管理)
在代码中访问到这个图片,基于这个图片构造出光标对象并设置就好了。
关于这个qrc机制上一讲有介绍,这里就不再赘言了。
这里的图像我们还是使用上一讲的狗头图像。
但是这里的访问不是像我们上面代码演示的那样,我们必须先访问到这个图片文件,然后借助这个图片对象来设置光标。
这里我们的访问图片的方式是通过“QPixmap”这个类,具体可以看后面的代码。
这个函数的后面两个参数,是用来控制鼠标的点击位置。同时如果这两个参数设置的太大了,Qt会直接扩大鼠标图标的大小。
同时我们想通过常规方式修改鼠标图像的大小可以直接模仿下面的伪代码。
pixmap = pixmap.scaled(100, 100);
通过这个函数对图片进行缩放,然后再设置进鼠标当中
注意缩放不是修改图片对象本身,而是返回一个新的图片对象副本,所以要赋值。
代码:
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QCursor>
#include <QPixmap>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button=new QPushButton(this);QPixmap tmp(":/dog.jpg");tmp=tmp.scaled(20,20);button->setCursor(QCursor(tmp,10,10));button->resize(300,300);button->move(200,200);button->setText("这是一个切换鼠标图片的按钮");}Widget::~Widget()
{delete ui;
}
由于截屏软件无法截取到鼠标,所以我们就不演示了,大家要是有兴趣可以直接实验。
补充说明:
我们每次想要使用鼠标图像,还要自己找图片太挫了,这里推荐一个免费的图标网站。
iconfont-阿里巴巴矢量图标库
二、font
font是什么意思呢?我们直接看一下翻译。
其实看到字体,我们已经大概猜出来这个属性的作用了。废话不多说,font这个属性就是负责控制文本的字体,大小,粗细程度,倾斜等属性。
我们下面看一下对应的API和具体的属性。
API:
属性:
属性 | 说明 |
---|---|
family | 字体家族,比如 "楷体"、"宋体"、"微软雅黑" 等 |
pointSize | 字体大小 |
不小心多打了一行 | |
weight | 字体粗细,以数值方式表示粗细程度,取值范围为 [0, 99],数值越大越粗 |
bold | 是否加粗,设置为 true 相当于 weight 为 75,设置为 false 相当于 weight 为 50 |
italic | 是否倾斜 |
underline | 是否带有下划线 |
strikeOut | 是否带有删除线 |
上述属性具体怎么设置,实际开发中,往往有专门的美工/设计/UED来进行确定,但是如果是一些小公司,没有美工甚至都没有产品经理,这个情况,咱们作为一个程序员,就可以参考一下别人的程序是怎么安排的,或者别人写的网页是怎么安排的。
我们下面直接演示一下,这些属性的具体表现。
演示一:通过图形化界面的方式来设置。
演示效果:
QtDesigner能够对界面的属性设置支持"实时预览”,改了啥属性,这边就能立即显示出来
通过属性编辑这样的方式,虽然能够快速方便的修改文字相关的属性,但是还不够灵活
如果程序运行过程中,需要修改文字相关的属性就需要通过代码来操作了。
演示二:通过代码实现我们的目的
1) 在界⾯中创建 label, objectName 使⽤默认的 label 即可.
2) 修改 widget.cpp
代码:
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QCursor>
#include <QPixmap>
#include <QFont>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button=new QPushButton(this);QPixmap tmp(":/dog.jpg");tmp=tmp.scaled(20,20);button->setCursor(QCursor(tmp,10,10));button->resize(300,300);button->move(200,200);button->setText("这是一个切换鼠标图片的按钮");//这是修改文本属性的代码;QFont font;//这是设置字体家族,就是设置字体样式font.setFamily("微软雅黑");//设置字体大小font.setPointSize(20);//设置字体是否加粗font.setBold(true);//设置字体是否倾斜font.setItalic(true);//设置字体下划线font.setUnderline(true);//设置字体删除线font.setStrikeOut(true);//最后将我们的font设置到我们的Label当中。ui->label_2->setFont(font);
}Widget::~Widget()
{delete ui;
}
3) 运⾏程序, 观察效果
三、tooltip
我们还是先看一下这个单词的含义,我们再去推测这个属性的作用。
我们知道当一个GUI程序,界面比较复杂,按钮啥的很多,这个时候我们把鼠标悬停到这个控件上的时候,就能弹出一个提示。
这个跳出来的文本框就是我们的tooltip的功能。
那我们下面看一下对应的API
这个属性的功能还是很简单的,我们下面直接演示一波。
这里我们使用代码的方式编写,目标是在一个小按钮上跳出提示。
演示:
代码:
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QCursor>
#include <QPixmap>
#include <QFont>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button=new QPushButton(this);QPixmap tmp(":/dog.jpg");tmp=tmp.scaled(20,20);button->setCursor(QCursor(tmp,10,10));button->resize(300,300);button->move(200,200);button->setText("这是一个切换鼠标图片的按钮");//这是修改文本属性的代码;QFont font;//这是设置字体家族,就是设置字体样式font.setFamily("微软雅黑");//设置字体大小font.setPointSize(20);//设置字体是否加粗font.setBold(true);//设置字体是否倾斜font.setItalic(true);//设置字体下划线font.setUnderline(true);//设置字体删除线font.setStrikeOut(true);//最后将我们的font设置到我们的Label当中。ui->label_2->setFont(font);//tooltip的演示代码QPushButton* button_1=new QPushButton(this);button_1->setToolTip("这是一个简单的小提示");button_1->setText("小按钮");
}Widget::~Widget()
{delete ui;
}
效果图:
注:如果想要使用控制显示时间的函数,要注意时间单位的转化关系。
1s = 1000 ms,1ms = 1000 us。
四、focusPolicy
这个属性的意思是焦点,就是我们平时在操作电脑的时候,计算机怎么知道我们键盘输入是向谁输入的呢?就是通过这个属性。
计算机中的"焦点”,对于键盘操作的效果非常明显,界面上有一个输入框,此时必须要选中这个输入框,接下来键盘按键才会输入到输入框中,如果选中的是别的控件,或者别的窗口,此时键盘的输入就不会进入到这个输入框中。
例如:
这个属性比较常见的应用就是我们在线笔试防作弊了。
我们在人家的网页中去做题,网页是属于始终获取到焦点的状态的,一旦你切到百度/其他程序(比如VS/IDEA)立刻人家的网页就能感知到"失去焦点”。服务器就能收集到你这样的动作
从而衡量你是否涉嫌作弊。
那我们下面来看一下,这个属性对应的API吧
一般来说,一个控件获取到焦点,主要是两种方式1. 鼠标点击,2. 键盘的 tab。
这个两个函数接口还是很好理解的,我们再来看一下什么是FocusPolicy。
Qt::FocusPolicy 是⼀个枚举类型.
取值如下 :
• Qt::NoFocus :控件不会接收键盘焦点
• Qt::TabFocus :控件可以通过Tab键接收焦点
• Qt::ClickFocus :控件在⿏标点击时接收焦点
• Qt::StrongFocus :控件可以通过Tab键和⿏标点击接收焦点 (默认值)
• Qt::WheelFocus : 类似于 Qt::StrongFocus , 同时控件也通过⿏标滚轮获取到焦点 (新增 的选项, ⼀般很少使⽤).
下面我们通过四个输入框,来演示focusPolicy的效果。
演示:
效果图:
我们发现选择对应选项的文本框,只能接受对应的方式的焦点。
第一个文本框什么方式都不接受,第二个文本框只能使用tab得到焦点,第三个文本框只能是鼠标左键,而第四个文本框这是两种方法都可以。
五、stylesheet
下面终于到了,我们本节博客的最后部分了。
这个属性就是可以让我们通过 CSS 设置 widget 的样式。
CSS (Cascading Style Sheets 层叠样式表) 本⾝属于⽹⻚前端技术.
主要就是⽤来描述界⾯的 样式. 所谓 "样式", 包括不限于 ⼤⼩, 位置, 颜⾊, 间距, 字体, 背景, 边框等.
我们平时看到的丰富多彩的⽹⻚, 就都会⽤到⼤量的 CSS.
Qt 虽然是做 GUI 开发, 但实际上和 ⽹⻚前端 有很多异曲同⼯之处. 因此 Qt 也引⼊了对于 CSS 的⽀持.
CSS 中可以设置的样式属性⾮常多.
基于这些属性 Qt 只能⽀持其中⼀部分, 称为 QSS (Qt Style Sheet) .
具体的⽀持情况可以参考 Qt ⽂档中 "Qt Style Sheets Reference" 章节. 此处只是进⾏⼀个简单的演⽰.
和CSS类似.QSS设置的样式也是键值对的格式,键和值之间使用:分隔。键值对和键值对之间,使用;分隔。
另外, Qt Designer 只能对样式的基本格式进⾏校验, 不能检测出哪些样式不被 Qt ⽀持. ⽐如 textalign: center 这样的⽂本居中操作, 就⽆法⽀持。
所以我们下面进行一个小的展示。
演示:
这个stylesheet的使用还是很简单的,我们是直接在designer的界面设置还是直接以硬编码的方式都是可以的。
由于不好截屏,这里就不对图形化界面的方式进行解释,我们明白它是右键对应的控件然后找到
“改变样式表”就好了
这是我们的选择的样式结构。
效果图:
六、一个小程序
在上面结合我们前面学习到的东西,我们现在结合一下,写个小程序吧,不复杂,就是实现一个夜间模式。
代码⽰例: 实现切换夜间模式.
1) 在界⾯上创建⼀个多⾏输⼊框 (Text Edit) 和两个按钮.
objectName 分别为 pushButton_light 和 pushButton_dark
2) 编写按钮的 slot 函数.
这两个槽函数的作用是切换Widget的颜色,这里我们想要切换颜色,就要使用stylesheet了,我们可以根据这个直接设置颜色
预备知识:#333 是深⾊, 但是没那么⿊. #fff 是纯⽩⾊. #000 是纯⿊⾊
演示:
我们发现我们的白天模式,并没有回到最开始的颜色,这是我们的颜色设置的问题,但是我们如何设置成原来相同的颜色呢?
那我们需要先了解一下关于显示器显示颜色的方法。
关于计算机中的颜⾊表⽰ 计算机中使⽤ "像素" 表⽰屏幕上的⼀个基本单位(也就是⼀个发亮的光点).
每个光点都使⽤三个字节表⽰颜⾊, 分别是 R (red), G (green), B (blue) ⼀个字节表⽰ (取值范 围是 0-255, 或者 0x00-0xFF).
混合三种不同颜⾊的数值⽐例, 就能搭配出千千万万的颜⾊出来.
• rgb(255, 0, 0) 或者 #FF0000 或者 #F00 表⽰纯红⾊.
• rgb(0, 255, 0) 或者 #00FF00 或者 #0F0 表⽰纯绿⾊.
• rgb(0, 0, 255) 或者 #0000FF 或者 #00F 表⽰纯蓝⾊.
这三个颜色也被称为计算机的三原色,注意与我们的艺术方面的三原色不同。
• rgb(255, 255, 255) 或者 #FFFFFF 或者 #FFF 表⽰纯⽩⾊.
• rgb(0, 0, 0) 或者 #000000 或者 #000 表⽰纯⿊⾊.
当然, 上述规则只是针对⼀般的程序⽽⾔是这么设定的. 实际的显⽰器, 可能有 8bit ⾊深或者 10bit ⾊深等, 实际情况会更加复杂
所以我们只要得知原来颜色的rgb是多少就可以了。如何获取呢,我们可以通过QQ截图自带的取色器获取。
这样我们就知道了,不过这里,博主就不再演示在博客里了。
代码:
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_dark_clicked()
{//我们的夜间模式,是不是要把我们的除文字以外的地方改变成黑色,文字变为白色。this->setStyleSheet("background-color: #333");ui->textEdit->setStyleSheet("background-color: #333; color: #fff;");//backgroud-color是指的是控件的背景色,而color是值指的是文字的颜色。ui->pushButton_light->setStyleSheet("color: #fff");ui->pushButton_dark->setStyleSheet("color: #fff");
}void Widget::on_pushButton_light_clicked()
{this->setStyleSheet("background-color: #f3f3f3");ui->textEdit->setStyleSheet("background-color: #fff; color: #000;");ui->pushButton_light->setStyleSheet("color: #000");ui->pushButton_dark->setStyleSheet("color: #000");
}
千万要注意这里的单词拼写,这里如果拼写出错,不会有任何报错,但是样式会不生效!
总结:
至此,我们完成了《QT 第八讲 --- 控件篇 (三)界面系列》的学习。我们详细探讨了如何通过cursor
、font
、tooltip
、focusPolicy
以及强大的stylesheet
来全方位地定制控件的外观、提示信息、交互行为和视觉效果。这些技术点赋予了我们精确控制用户界面细节的能力,是提升应用专业度和用户体验不可或缺的部分。
掌握了这些界面定制的基础后,我们将在下一讲《QT 第九讲 --- 控件篇 (四)button》中,聚焦于用户交互中最频繁使用的控件之一——按钮(QPushButton
及其变种)。我们将深入探讨按钮的各种状态、信号、常用功能以及如何利用本讲所学知识(特别是样式表)来创建形态各异、功能丰富的按钮,实现更生动的用户交互体验。
我们下期见!