系列文章目录
文章目录
前言
对于本系列文字介绍的Widget,QT Designer 左边有很多控件可以使用,之后的文章中也会介绍通过一些工具可以美化,上古时期是画图,现在都是越来越优化的控件。
Widget 是 Qt 中的核心概念. 英⽂原义是 “小部件”, 我们此处也把它翻译为 “控件”
控件是构成⼀个图形化界面的基本要素.
QWidget的属性
在 Qt 中, 使⽤ QWidget 类表⽰ “控件”. 像按钮, 视图, 输⼊框, 滚动条等具体的控件类, 都是继承自QWidget.
可以说, QWidget 中就包含了 Qt 整个控件体系中, 通用的部分
1.enable属性
描述了一个控件是否处于可用状态,相对的概念也就是“禁用”。
- 禁用是指该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。
- 如果一个widget被禁用,widget的子元素也被禁用
API | 说明 |
---|---|
isEnable() | 获取到控件的可用状态。 |
setEnabled() | 设置控件是否可用,true可用 false 禁用 |
ui->setupUi(this);
QPushButton* button = new QPushButton(this);
button->setText("按钮");
//按钮处于禁止状态
button->setEnabled(false);
用户操作触发设置禁用按钮
在同一个界面中,要求不同的控件的objectName也是必须不同的。可以通过ui->objectName方式来获取到对应的控件对象。
ui->pushButton //第一个按钮对象
ui->pushButton_2//第二个按钮对象
元编程,QT会根据ui文件生成ui.h,文件生成的过程中就会感知到,界面上有哪些控件,每个控件大的objectName
当前自动生成的objectName以按钮类型+下划线+数字来命名,而这样的习惯不好,要习惯根据功能命名
按钮提供的信号很多,clicked最常用,clicked有两个版本,有参数或无参数的,有参数的bool表示当前是否处于被勾选的状态。QPushButton选择无参数的即可
//切换第一个按钮的禁用状态
//1.先获取到当前按钮状态
bool enable = ui->pushButton->isEnabled();
if(enable)
{
ui->pushButton->setEnabled(false);
}
else
{
ui->pushButton->setEnabled(true);
}
2.geometry属性
位置和尺寸
x y:左上角的位置
height: width://高度宽度
API | 说明 |
---|---|
geometry() | 获取到控件的位置和尺寸,返回结果是一个QRect,包含了x,y,width,height,xy为左上角坐标 |
setGeometry()setGeometry(int x, int y , int width ,int height) | 设置空间的位置和属性 |
QT对几何概念进行了封装,QPoint(点)QRect(矩形),属于小对象,属性少占用空间小。C++使用上述对象,通常会按照值的方式
之前文章提到的move只是修改位置,setGeometry既可以修改位置,又可以修改尺寸
注意选中的名字之后,再通过右下角属性栏修改objectName
使用四个按钮修改目标pushButton的位置
void Widget::on_pushButton_up_clicked()
{
//获取到target按钮的位置
QRect rect =ui->pushButton_target->geometry();
qDebug()<<rect;
rect.setY(rect.y()-5);//成员函数 = 方法
ui->pushButton_target->setGeometry(rect);
}
void Widget::on_pushButton_down_clicked()
{
QRect rect =ui->pushButton_target->geometry();
qDebug()<<rect;
rect.setY(rect.y()+5);//成员函数 = 方法
ui->pushButton_target->setGeometry(rect);
}
void Widget::on_pushButton_left_clicked()
{
QRect rect =ui->pushButton_target->geometry();
qDebug()<<rect;
rect.setX(rect.x()-5);//成员函数 = 方法
ui->pushButton_target->setGeometry(rect);
}
void Widget::on_pushButton_right_clicked()
{
QRect rect =ui->pushButton_target->geometry();
qDebug()<<rect;
rect.setY(rect.y()+5);//成员函数 = 方法
ui->pushButton_target->setGeometry(rect);
}
上述代码实际的执行效果是调整左上角的位置(修改了按钮的大小)
如果想让按钮平移?(保持尺寸不变)
不再修改QRect,而是通过QRect基于setGeometry第二个版本,重写位置。
void Widget::on_pushButton_up_clicked()
{
//获取到target按钮的位置
QRect rect =ui->pushButton_target->geometry();
qDebug()<<rect;
// rect.setY(rect.y()-5);//成员函数 = 方法
// ui->pushButton_target->setGeometry(rect);
ui->pushButton_target->setGeometry(rect.x(),rect.y()-5,rect.width(),rect.height());
//实现按钮的向上平移
}
给男神表白
clicked ->点击就挪开
pressed->鼠标按下就挪开
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
srand(time(0));//秒级时间戳
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_accept_clicked()
{
ui->label->setText("爱你");
}
void Widget::on_pushButton_reject_clicked()
{
}
void Widget::on_pushButton_reject_pressed()
{
//点击后挪走
//生成随机数确定新的位置this
//1.当前窗口尺寸
int width = this->geometry().width();
int height = this->geometry().height();
//2.重新生成按钮的位置(rand设置随机种子)
int x = rand()%width;//1-width之内的一个整数
int y = rand()%height;
//3.移动按钮的位置
ui->pushButton_reject->move(x,y);
}
- windowframe的影响
如果widget作为一个窗口(带有标题栏,最小化,最大化,关闭)计算尺寸就有两种算法 window frame和不包含window frame。
- x(),y(),frameGeometry(),pos(),move() 按照window frame计算的
- geometry(),width(),height(),rect(),size(),按照不包含来计算
- 不是窗口的widget,两者是相同的
具体内容参考官方文档
可以用上述代码验证引用,下面的代码放到构造函数中显然不可以,因此写一个按钮来验证(那个时候widget还没有形成)
QRect rect1 = this->geometry();
QRect rect2 = this->frameGeometry();
qDebug()<<rect1;
qDebug()<<rect2;
3. windowTitile属性
该属性从属于windowstitle属性,从属于QWidget,QWidget是一个广泛的概念,windowTitle属性只针对顶层窗口这样的QWidget才有效。谁是窗口才能给谁设置window,但是写了这样代码不会报错,很暴躁!
4.WindowIcon窗口图标
类似于windowtitle,只能针对顶层窗口
API | 说明 |
---|---|
windowIcon() | 获取到控件的窗口图标,返回QIcon对象 |
setWindowIcon(const QIcon& icon) | 设置控件窗口图标 (主要使用) |
类似于windowtitle,只能针对顶层窗口
之前都是再堆上创建对象,目的是保证控件的生命周期是足够的,通过QT对象树来释放
WQIcon本身是一个比较小的对象,创建出来后要设置到某个QWidget里面,本身是否释放不影响图标的最终显示
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:/roy.jpg");//绝对路径的方式
this->setWindowIcon(icon);
}
Widget::~Widget()
{
delete ui;
}
文件路径"/“或者”\",C++11引用raw string来解决上述问题,字符串不包含任意转义字符
r("d:\)???
通过绝对路径的方式不科学,程序要放到用户电脑上,无法确定用户的路径和自己的一致。因此使用相对路径是更好的。
绝对路径:就是文件的真正存在的路径,是指从硬盘的根目录(盘符)开始,进行一级级目录指向文件。
相对路径:以 . (表示当前路径) 或者 以 … (表示当前路径上级路径) 开头的路径. 其中,经常也
会省略. 相对路径的前提是需要明确 当前工作目录。
qrc机制
-
确保图片所在的路径在目标用户机存在
-
确保图片不会被搞丢了
-
引入额外的xml文件,在xml中把资源导入进来,并且在xml中记录。编译项目的时候,根据qrc中的描述信息,找到内容,提取二进制数据,转成代码编译到exe中
-
缺点:无法导入太大的资源文件
qrc的使用方式
创建qrc文件,不带中文和特殊符号
图片导入
- 1)“前缀”(prefix)可以理解为虚拟的目录 这个目录没有在电脑上真是存在,是QT自己抽象出来的,二进制数据->C++代码。
为了方便QT访问图片,QT自己抽象除了虚拟的目录 。为方便使用将目录改为 “/” - 2)把刚才的rose.jpg这个图片导入到资源文件中点击addfile(add file在 add prefix前是禁用的)
(要确保导入的图片在resource.qrc的同级目录或者同级目录的子目录)
然后我们导入图片的代码变成了
QIcon icon(":/rose.jpg");
当代码中需要访问qrc中管理的文件,路径要带上冒号前缀 ”前缀+文件名“
build文件中,导入的图片资源转成qrc_resource.cpp,一起编译到了exe中,不怕弄丢
5.WindowOpacity属性
设置窗口的透明度(半透明效果)很容易,但是导致系统比较卡
API | 说明 |
---|---|
windowOpacity() | 获取到控件的不透明数值,返回float 取值为0.0~1.0,其中0.0表示全透明,1.0不透明 |
setWindowOpacity(flow n) | 设置控件的不透明数值 |
按钮控制窗口的不透明度
void Widget::on_pushButton_add_clicked()
{
float opacity=this->windowOpacity();
if (opacity>=1.0)
{
return;
}
qDebug()<<opacity;
opacity+=0.1;
this->setWindowOpacity(opacity);
}
void Widget::on_pushButton_sul_clicked()
{
float opacity=this->windowOpacity();
if (opacity<=0.0)
{
return;
}
qDebug()<<opacity;
opacity-=0.1;
this->setWindowOpacity(opacity);
}
出现以下问题:
- 窗口的不透明度变化不是精确的。
数据在内存中的存储
- 整数
- 浮点数: IEEE754标准,二进制科学计数法表示。符号位,有效数字(二进制,且小于0小数部分0.5 0.25…有效数字长度有限,无法凑出非常接近0.1的数字),指数部分
运算速度快,占用空间小,但是小数无法精确表示。因此对于float的比较不能==,要作差。
- 代码中加了判定条件,不加判定条件也是可以的。超过1.0的数字设置不进去,setWindowOpacity中进行了设置。
防御性编程(别人犯错了,自己不会遭受很大的伤害)
大多数时候,大的项目拆分很多模块,不同的人分别完成,对别人的API,是否进行检查呢?答案是肯定的,两方都要进行判定!防止任何一方的失误
6.cursor(光标)
API | 属性 |
---|---|
cursur() | 获取当前属性 |
setCursor() | 设置widget光标的形状,仅仅停留的时候生效 |
QGuiApplication::setOverrideCursor(const QCursor& cursor) | 设置全局光标的形状,堆程序中整个Widget都生效 |
最快捷的修改方式就是从ui属性这里直接修改,可以看到很多内置的图标。
用代码方式
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QCursor cursor(Qt::WaitCursor);//等待图标
ui->pushButton->setCursor(cursor);
//注意给窗口设置和给按钮设置的区别
}
自定义图片设置光标
准备图片,导入到项目,代码访问图片构造光标
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//QPixmap表示图片~
QPixmap pixmap(":/roy");//访问图片
//图片大了进行缩放
pixmap = pixmap.scaled(100,100);
//构造光标对象
//QCursor cursor(Qt::WaitCursor);
QCursor cursor(pixmap,10,10);//默认点击左上角 10,10表示左上角原点,10,10真正点击的位置
//图片大了进行缩放
ui->pushButton->setCursor(cursor);
}
如何找图片?阿里巴巴矢量图标库免费下载
7.font(字体)
API | 说明 |
---|---|
font() | 获取当前widget字体,返回QFont |
setFont(const QFont& font) | 设置当前widget的字体 |
QFont
属性 | 说明 |
---|---|
family | |
pointSize | 字体大小px为单位 |
weidgt | 粗细【0-99】数值越大越粗 |
bold | 是否加粗true75/ false相当于weight为50 |
italic | 是否倾斜 |
underline | 下划线 |
strikeOut | 删除线 |
具体设置往往是美工/设计/UED来确定 |
平时通过浏览器开发者工具,可以看到文字属性信息
除了函数方式,还可以通过QT designer通过相关属性进行修改
代码方式
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QLabel* label = new QLabel(this);
label->setText("文本");
QFont font;
font.setFamily("仿宋");
font.setPixelSize(30);
font.setBold(true);
font.setItalic(true);
label->setFont(font);
}
8.ToolTip
按钮比较复杂,按钮很多
- 功能:当按钮悬停到控件的时候,就能弹出一个提示
API | 说明 |
---|---|
setToolTip | 设置内容,鼠标悬停在widget会有提示说明 |
setToolTipDuring() | 设置提示的时间,单位ms,时间到后自动消失 |
ToolTIp是给用户看的,代码中一般不用获取到toolTip |
msec 毫秒QT中采用的
sec 秒
usec 微秒
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->pushButton_yes->setToolTip("这个是 yes 按钮");
ui->pushButton_yes->setToolTipDuration(3000);
ui->pushButton_no->setToolTip("这个是 no 按钮");
ui->pushButton_no->setToolTipDuration(10000);
}
9. focusPolicy(控件焦点)
- 获取控件的焦点
- 键盘很明显,界面上有输入框,此时必须选中输入框(焦点元素游戏)在线笔试/切换界面就会失去焦点。
控件获取到焦点主要是两种方式
- 鼠标点击
- 键盘的Tab
API | 说明 |
---|---|
fousPolicy | 获取widget的focusPolicy,返回Qt::FocusPolicy |
setFocusPolicy(Qt::FousPolicy policy) | 设置widget的focusPolicy |
Qt::FousPolicy 是枚举类型有以下类型
枚举类型 | |
---|---|
Qt::NoFocus | 不会接收键盘焦点比如 label |
Qt::TabFocus | 通过tab接收焦点 |
Qt::ClickFocus | 鼠标点击接收焦点 |
Qt::StrongFocus | tab和鼠标点击(默认) |
Qt::WheelFocus | 类似于Qt:: strongFocus+滚轮获取焦点(很少使用) |
看到这里可以自己手动画几个可编辑输入框,理解不同的focusPolicy。
10. stylesheet属性
QT中引用了对css的支持,可以设置widget的样式
css:层叠样式表,在网页开发的时候,设置网页样式的方式,非常丰富好看
QT参考着搞了一套QSS,功能缺失很多,但也能完成很多的效果
采用键值对的格式,键和值之间分隔冒号,键值对之间分隔用分号
代码方式
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置窗口的样式
this->setStyleSheet("background-color:white;");
}
计算机中有无数种颜色:RGB 红绿蓝和光的三原色是有区别的。
#(255,255,255) FF00FF
采取以上颜色表示方式
在微信或者QQ截图中,对图片截图,内置了取色器(240,240,240)
总结
本文总结了QT框架中,Widget的相关属性,该属性适用于整个widget页面。
学习每个属性的最好办法就是动手写一写,如果有问题也可以评论区留言,本作者看到啦就会回复,一起学习共同进步!