文章目录
- 前言
- enabled
- geometry
- windowTitle
- windowIcon
- windowOpacity
- cursor
- font
- toolTip
- focusPolicy
- styleSheet
前言
Qt中的各种控件,都是继承自QWidget
类,了解这个类的属性方法之后,后续的控件也通用
enabled
enabled
描述了一个控件是否处于“可用”状态
和“可以”相对的概念叫“禁用”
“禁用”状态指的是该控件不能接收任何用户输入的事件了,并且外观上是灰色的;此外,如果一个控件被禁用,那么它的子元素也将被禁用
AIP | 说明 |
---|---|
isEnabled() | 获取控件可用状态 |
setEnabled | 设置控件是否可用,true 表示可用,false 表示禁用 |
widget.h
:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void handle();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
:
#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QtDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton *button = new QPushButton(this);
button->setText("按钮");
//设置按钮处于禁用状态
button->setEnabled(false);
connect(button, &QPushButton::clicked, this, &Widget::handle);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle()
{
qDebug() << "handle()";
}
也可以通过一个按钮来切换另一个按钮的状态
在同一个界面当中,要求不同的控件
objectName
不能重复,这样后续就能通过ui->objectName
访问到对应的控件。这个自动生成的
objectName
是有点规律的,控件类型 + 下划线 + 数字
,这个以数字方式命名,不是一个好习惯,我们可以修改
geometry
这个属性可用认为是四个属性的统称:x、y、width、height
API | 说明 |
---|---|
geometry() | 获取控件的位置和尺寸,返回结果是一个QRect (矩形),包含了x、y、width、height,其中(x,y)是左上角的坐标 |
setGeometry(QRect) setGeometry(int x, int y, int width, int height) | 设置控件的位置和尺寸,可用直接设置一个QRect ,也可以分四个属性单独设置 |
move
只是修改位置,geometry
既可以修改位置、也可以修改尺寸
通过四个方向键按钮,来控制target
:
#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_up_clicked()
{
//获取target本质的geometry
QRect rect = ui->pushButton_target->geometry();
//可用直接打印
qDebug() << rect;
//设置y轴
rect.setY(rect.y() - 5);
}
void Widget::on_pushButton_down_clicked()
{
QRect rect = ui->pushButton_target->geometry();
qDebug() << rect;
rect.setY(rect.y() + 5);
}
void Widget::on_pushButton_left_clicked()
{
QRect rect = ui->pushButton_target->geometry();
qDebug() << rect;
rect.setX(rect.x() - 5);
}
void Widget::on_pushButton_right_clicked()
{
QRect rect = ui->pushButton_target->geometry();
qDebug() << rect;
rect.setX(rect.x() + 5);
}
执行发现,只是调整了左上角的位置,左上角改变的同时,高度和宽度也改变了
如果想实现“平移”的效果,尺寸保存不变,就不用修改QRect
,可用通过QRect
基于setGeometry
第二个版本的函数重新设置位置即可:
void Widget::on_pushButton_up_clicked()
{
//获取target本质的geometry
QRect rect = ui->pushButton_target->geometry();
//可用直接打印
qDebug() << rect;
//设置y轴
//rect.setY(rect.y() - 5);
//以上都是局部变量,获取target,将矩形设置进去
//ui->pushButton_target->setGeometry(rect);
ui->pushButton_target->setGeometry(rect.x(), rect.y()-5, rect.width(), rect.height());
}
//...
可用基于此,做一个简单的小程序:
#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() { //挪走按钮 //生成随机数 //获取当前窗口尺寸 // int width = this->geometry().width(); // int height = this->geometry().height(); // //生成位置 // int x = rand() % width; // int y = rand() % height; // ui->pushButton_reject->move(x, y); } //pressed 点击鼠标之后就触发 void Widget::on_pushButton_reject_pressed() { int width = this->geometry().width(); int height = this->geometry().height(); //生成位置 int x = rand() % width; int y = rand() % height; ui->pushButton_reject->move(x, y); }
关于window frame的影响,可以看此篇文章:Qt中window frame的影响
windowTitle
API | 说明 |
---|---|
windowTitle() | 获取控件窗口的标题 |
setWindowTitle(const QString& title) | 设置控件的窗口标题 |
windowTitle
属性是属于QWidget
,而QWidget
是一个广泛的概念,例如一个按钮、一个输入框,都属于QWidget
。
windowTitle
属性只针对顶层窗口这样的QWidget
才有效当前设置了窗口标题,也给按钮设置了标题,窗口标题正常显式,按钮没有显式、也没有报错。
此时“没有报错”,是不太科学的
windowIcon
windowIcon
表示窗口的图标,下面这些就是窗口的图标
想要改变窗口图标,可以采用下面的API:
API | 说明 |
---|---|
windowIcon() | 获取控件窗口图标,返回QIcon对象 |
setWindowIcon(const QIcon& icon) | 设置控件的窗口图标 |
这个也是针对顶层窗口使用的
#include "widget.h"
#include "ui_widget.h"
#include<QIcon>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QIcon icon("./logo.jpg");
this->setWindowIcon(icon);
}
Widget::~Widget()
{
delete ui;
}
Tips1:
之前一般都是在堆上创建对象,而这里QIcon对象直接在栈上创建。
这是因为要确保当前对象的生命周期是足够的,要通过Qt对象树来释放;
而QIcon自身是一个比较小的对象,创建出来之后要设置到某个QWidget里面,QIcon对象本身释放与否,不需要图标的显示;
另外QIcon也不支持对象树机制,无法给它指定父对象
Tips2:
这里的路径读取,采用了
/
作为分隔符,这是因为C++中\
是转义字符,会影响读取如果想使用
\
作为分隔符,C++11引入raw string
,这里面的字符串就表示不包含任何转义字符R(“C:\ProgramFiles\xxx\xx.jpg”)
Tips3:
设置路径一般采用相对路径,因为程序可能是要给别人使用的,无法确保我们的路径和用户的路径一致。
这个图片要放到运行程序的路径下:
如果用户将图片不小心弄没了,这还是比较麻烦。Qt里面引入了qrc机制,从根本上解决这两个问题:
- 确保图片所在路径在目标用户机器上存在
- 确保图片不会丢失
qrc
机制讲解:Qt qrc机制
运行之后,窗口的图标就改变了
windowOpacity
windowOpacity
可以设置窗口透明度
API | 说明 |
---|---|
windowOpacity() | 获取控件的不透明数值 返回float,取值为[0.0, 1.0],其中0.0表示全透明,1.0表示完全不透明 |
setWindowOpacity() | 设置控件的不透明数值 |
#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;
}
qDebug() << opacity;
opacity += 0.1;
this->setWindowOpacity(opacity);
}
void Widget::on_pushButton_sub_clicked()
{
float opacity = this->windowOpacity();
if(opacity <= 0.0)
{
return;
}
qDebug() << opacity;
opacity -= 0.1;
this->setWindowOpacity(opacity);
}
事件运行的时候,查看输出信息,窗口透明度的变化,并不是精确的
这是因为浮点数在内存中存储,要根据IEEE 754标准,规定浮点数要使用二进制位科学计数法的方法来表示,一个浮点数分为3部分:
- 符号位
- 有效数字
- 指数部分
使用二进制表示有效数字部分,第一位0.5(2-1)、第二位0.25(2-2)、第三位0.125(2-3)…
由于长度有限,就无法精确表示0.1这样的数字,所以就显示出了这些有误差的数字
具体方面,可以看此篇文章:数据的存储
我们代码当中加了判定条件,看opacity
是否在[0.0, 1.0]这个区间,其实不加也是可以的,因为超出范围的设置不进去,setWindowOpacity
内部做了处理。
验证发现,确实setWindowOpacity
内部做出了处理,但是实际开发当中,还是建议加上,出于于“防御性编程”的角度考虑,double check
cursor
修改鼠标光标的样式,指向不同控件,有不同效果
API | 说明 |
---|---|
cursor() | 获取当前widget的cursor属性,返回QCursor对象 当鼠标悬停在该widget上时,就会回显出对应的形状 |
setCursor(const QCursor& cursor) | 设置该widget光标的形状,仅在鼠标停留在该widget上时生效 |
QGuiApplication::setOverrideCursor(const QCursor& cursor) | 设置全局光标的形状,对整个程序中所以的widget都会生效 覆盖上面的setCurosr设置的内容 |
可以通过图形化界面的方式直接设置:
通过代码方式:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QCursor cursor(Qt::WaitCursor); //等待光标
ui->pushButton->setCursor(cursor);
}
Widget::~Widget()
{
delete ui;
}
这些都是Qt内置的光标形状:
这些内置的光标图片,看着稍微有点古老,Qt允许我们通过自定义图片来设置光标。
和设置窗口图标操作相似,准备好图片,然后导入到qrc文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//访问图片文件
QPixmap pixmap(":/ikun.png");
//构造光标对象
//图片左上角为原点, 找到10,10这个位置,为鼠标真正点击的位置
QCursor cursor(pixmap, 10, 10);
//设置光标
this->setCursor(cursor);
}
Widget::~Widget()
{
delete ui;
}
如果图片太大/小,可采用
QPixmap
通过的scaled
函数,对图片进行缩放QPixmap pixmap(":/ikun.png"); pixmap = pixmap.scaled(50, 50);
光标网站推荐:iconfont-阿里巴巴矢量图标库
font
API | 说明 |
---|---|
font() | 获取当前widget的字体信息,返回QFont对象 |
setFont(const QFont& font) | 设置当前widget的字体信息 |
关于QFont:
属性 | 说明 |
---|---|
family | 字体家族 例如“楷体”、“宋体”、“微软雅黑”等 |
pointSize | 字体大小 |
weight | 字体粗细 以数值方式表示粗细程度,取值范围为[0, 99],数值越大,越粗 |
bold | 是否加粗 设置为true,相当于weight为75;设置为false,相当于weight为50 |
italic | 是否倾斜 |
underline | 是否带下划线 |
strikeOut | 是否带删除线 |
上述属性具体怎么设置,在实际开发中,会有专门的美工/设计/UED来确定
可以通过图形化设置:
这样修改很方便,但是不够灵活,因为程序运行的时候,可能需要修改字体,这时候就需要代码来操作了
代码设置:
#include "widget.h"
#include "ui_widget.h"
#include<QLabel>
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);
font.setUnderline(true);
font.setStrikeOut(true);
//设置进label当中
label->setFont(font);
}
Widget::~Widget()
{
delete ui;
}
toolTip
一个GUI程序,界面比较复制,各种控件比较多,这些控件具体是干嘛的,可能就不是很清楚。
toolTip
机制就可以当把鼠标悬停到这个控件的时候,就会弹出提示。
API | 说明 |
---|---|
setToolTip | 设置toolTip 鼠标悬停在该widget上时,会有提示说明 |
setToolTipDuring | 设置toolTip提示时间,单位ms 时间到之后toolTip自动消失 |
图形化界面设置:
代码设置:
#include "widget.h"
#include "ui_widget.h"
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(3000);
}
Widget::~Widget()
{
delete ui;
}
focusPolicy
设置控件获取焦点的策略
所谓的“焦点”,指的就是能选中这个元素,接下来的操作,都在针对该焦点元素进行的。
例如点击一个文本框,接下来键盘输入的内容,都是针对这个文本框的
一般来说,获取控件焦点主要通过2种方式:
- 鼠标点击
- 键盘tab
Qt通过了api,可以控制获取焦点的行为
API | 说明 |
---|---|
focusPolicy() | 获取该widget的focusPolicy 返回Qt::FocusPolicy |
setFocusPolicy(Qt::FocusPolicy) | 设置widget的focusPolicy |
Qt::FocusPolicy
是⼀个枚举类型,取值如下:
Qt::NoFocus
:控件不会接收键盘焦点Qt::TabFocus
:控件可以通过Tab键接收焦点Qt::ClickFocus
:控件在⿏标点击时接收焦点Qt::StrongFocus
:控件可以通过Tab键和⿏标点击接收焦点 (默认值)Qt::WheelFocus
: 类似于 Qt::StrongFocus , 同时控件也通过⿏标滚轮获取到焦点 (新增的选项, ⼀般很少使⽤).
通过图形化设置的,默认就是StrongFocus
这里就可以修改:
styleSheet
这个叫做样式标,通过CSS设置widget的样式
CSS:层叠样式表,在前端当中,设置网页样式的方式。Qt参考CSS,弄了自己的一套QSS
样式:描述界面具体是什么样子
通过代码实现日间、夜间模式的切换:
#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_light_clicked()
{
//设置窗口样式
this->setStyleSheet("background-color: white;");
//设置输入框样式
ui->plainTextEdit->setStyleSheet("background-color: white; color: black");
//设置按钮样式
ui->pushButton_light->setStyleSheet("color: black;");
ui->pushButton_dark->setStyleSheet("color: black;");
}
void Widget::on_pushButton_dark_clicked()
{
//设置窗口样式
this->setStyleSheet("background-color: black;");
//设置输入框样式
ui->plainTextEdit->setStyleSheet("background-color: black; color: white");
//设置按钮样式
ui->pushButton_light->setStyleSheet("color: white;");
ui->pushButton_dark->setStyleSheet("color: white;");
}
这个恢复成日间模式,和原始的不一样
计算机当中的颜色表示用RGB表示,一般并不会直接用
white
、red
这些直接表示我们可以采用取色器(截图或者画图板),获取当前的颜色:
然后设置进去即可: