一、控件概念
界面上各种元素、各种部分的统称(如按钮、输入框、下拉框、单选复选框...)
Qt作为GUI开发框架,内置了各种的常用控件,并支持自定义控件。
二、控件体系发展
1.没有完全的控件,需要使用绘图API手动绘制界面。
2.引入控件的概念,只有一些常用的控件,数量有限(按钮,输⼊框,单选框,复选框等),如html的原生控件。
3.拥有较为完整的控件体系,基本可以覆盖GUI开发的大部分场景。
例如早期的MFC,VB,C++Builder,Qt,Delphi,后来的AndroidSDK,JavaFX,前端的各种UI库等。
三、QWidget类
Qt的各种控件,均继承自QWidget,了解QWidget的属性和方法就了解了Qt控件的通用部分。
QtCreator代码中,选中控件类型,按F1查看文档。
核心属性
1.enabled
- 作用:表示控件是否可使用,true表示可用,false表示禁用。
禁用状态:不接收用户的输入事件,外观上往往是灰色的。
如果一个控件对象被禁用,那么该对象下的子元素也会被禁用。
- 相关API:
|--------------|--------|
| isEnabled() | 获取控件状态 |
| setEnabled() | 设置控件状态 |
示例

通过其他按钮,控制该按钮的可用状态
拖拽添加按钮控件,右键转到槽定义

2.geometry
- 作用:位置和尺寸,x、y、width、height
坐标以父元素作为参考进行设置。
左手坐标系,横x,纵y。高为height,宽为width。
- 相关API:
|--------------------------------------------------|------------------------|
| geometry() | 获取控件的位置和尺寸。返回结果为QRect。 |
| setGeometry(QRect) | 设置位置和尺寸 |
| setGeometry(int x, int y, int width, int height) | 设置位置和尺寸 |
- 示例
1.使用setGeometry(QRect),使用QRect来设置坐标和宽高
效果:改变矩形x,y时,宽高自动随之变化,移动了矩形的左上角位置,而右下角位置不变。
cpp
void Widget::on_pushButton_up_clicked()
{
//1.获取geometry
QRect rect=ui->pushButton_target->geometry();
qDebug()<<rect;
//2.设置geometry
rect.setY(rect.y()-5);
ui->pushButton_target->setGeometry(rect);
}
void Widget::on_pushButton_left_clicked()
{
//1.获取geometry
QRect rect=ui->pushButton_target->geometry();
qDebug()<<rect;
//2.设置geometry
rect.setX(rect.x()-5);
ui->pushButton_target->setGeometry(rect);
}
void Widget::on_pushButton_down_clicked()
{
//1.获取geometry
QRect rect=ui->pushButton_target->geometry();
qDebug()<<rect;
//2.设置geometry
rect.setY(rect.y()+5);
ui->pushButton_target->setGeometry(rect);
}
void Widget::on_pushButton_right_clicked()
{
//1.获取geometry
QRect rect=ui->pushButton_target->geometry();
qDebug()<<rect;
//2.设置geometry
rect.setX(rect.x()+5);
ui->pushButton_target->setGeometry(rect);
}

2.使用setGeometry(int x, int y, int width, int height)
修改x,y时,宽高不会自动变化,实现平移的效果。
cpp
void Widget::on_pushButton_up_clicked()
{
//1.获取geometry
QRect rect=ui->pushButton_target->geometry();
qDebug()<<rect;
//2.设置geometry
// rect.setY(rect.y()-5);
// ui->pushButton_target->setGeometry(rect);
ui->pushButton_target->setGeometry(rect.x(),rect.y()-5,rect.width(),rect.height());
}
void Widget::on_pushButton_left_clicked()
{
//1.获取geometry
QRect rect=ui->pushButton_target->geometry();
qDebug()<<rect;
//2.设置geometry
// rect.setX(rect.x()-5);
// ui->pushButton_target->setGeometry(rect);
ui->pushButton_target->setGeometry(rect.x()-5,rect.y(),rect.width(),rect.height());
}
void Widget::on_pushButton_down_clicked()
{
//1.获取geometry
QRect rect=ui->pushButton_target->geometry();
qDebug()<<rect;
//2.设置geometry
// rect.setY(rect.y()+5);
// ui->pushButton_target->setGeometry(rect);
ui->pushButton_target->setGeometry(rect.x(),rect.y()+5,rect.width(),rect.height());
}
void Widget::on_pushButton_right_clicked()
{
//1.获取geometry
QRect rect=ui->pushButton_target->geometry();
qDebug()<<rect;
//2.设置geometry
// rect.setX(rect.x()+5);
// ui->pushButton_target->setGeometry(rect);
ui->pushButton_target->setGeometry(rect.x()+5,rect.y(),rect.width(),rect.height());
}
void Widget::on_pushButton_target_clicked()
{
}

3.告白程序
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
srand(time(NULL));
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_accept_clicked()
{
ui->label->setText("今天开始是我们的第一天");
}
void Widget::on_pushButton_regect_clicked()
{
//点击即平移按钮到随机位置。限制在窗口内部
//获取窗口尺寸大小
QRect rect=this->geometry();
int width=rect.width();
int height=rect.height();
int x=rand()%width;
int y=rand()%height;
//方法一:setGeometry
// QRect rect1=ui->pushButton_regect->geometry();
// ui->pushButton_regect->setGeometry(x,y,rect1.width(),rect1.height());
//方法2:move
ui->pushButton_regect->move(x,y);
}

注册pressed信号:鼠标点击,未释放时触发信号
void Widget::on_pushButton_regect_pressed()
{
//点击即平移按钮到随机位置。限制在窗口内部
//获取窗口尺寸大小
QRect rect=this->geometry();
int width=rect.width();
int height=rect.height();
int x=rand()%width;
int y=rand()%height;
//方法一:setGeometry
// QRect rect1=ui->pushButton_regect->geometry();
// ui->pushButton_regect->setGeometry(x,y,rect1.width(),rect1.height());
//方法2:move
ui->pushButton_regect->move(x,y);
}
需要鼠标挪动到按钮上,不点击,就触发信号的效果。需要学习Qt的事件机制,后面再学习。
window frame对坐标的影响
两种窗口坐标:包含window frame的和不包含windowframe的
windowframe就是带有标题栏,最小化,最⼤化,关闭按钮,的整个窗口。
不包含windowfram的窗口就是Widget控件本身。

Qt提供了包含和不包含windowframe的各种坐标API。
包含windowframe的坐标API:
|-------------------|-------------------------------------------------------------------------------|
| x() | 获取x坐标 |
| y() | 获取y坐标 |
| frameGeometry() | 返回QRect对象。 QRect相当于QPoint和QSize的结合体 可以获取x,y,width,height 可以设置x,y,width,height |
| pos() | 返回QPoint对象 可以获取x(),y(), 设置setX(),setY() |
| move(int x,int y) | 移动控件 |
不包含windowframe的坐标API:
|------------|-----------|
| geometry() | 返回QRect对象 |
| width() | 返回宽 |
| height() | 返回高 |
| rect() | 返回QRect对象 |
| size() | 返回QSize对象 |
查看区别:
cpp
#include "widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//widget对象构造函数中,获取到的两种坐标是一样的,widget还没有挂到windowframe上
//需要在构造函数结束之后,然后挂到对象树上之后
// QRect rect1=this->geometry();
// QRect rect2=this->frameGeometry();
// qDebug()<<rect1;
// qDebug()<<rect2;
QPushButton* button=new QPushButton(this);
button->setText("按钮");
connect(button,&QPushButton::clicked,this,&Widget::handel);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handel()
{
QRect rect1=this->geometry();
QRect rect2=this->frameGeometry();
qDebug()<<rect1;
qDebug()<<rect2;
}

以整个屏幕的左上角为坐标原点
窗口含windowframe的坐标,x=559,y=172
不含windowframe的坐标,x=560,y=210
3.windowTitle
表示:窗口标题
API:|---------------------------------------|-----------|
| windowTitle() | 获取控件的窗口标题 |
| setWindowTitle(const QString& title) | 设置控件窗口标题 |
set标题只对顶层窗口生效,但子控件调用时,没有产生效果,也不会报错。
4.windowIcon
表示:窗口图标
API:
|-----------------------------------|------------------|
| windowIcon() | 获取窗口图标,返回QIcon对象 |
| setWindowIcon(const QIcon& icon) | 设置窗口图标 |
只针对顶层窗口生效。
注意:
1.QIcon对象创建在栈上
QIcon icon(".\image\icon.png");//不在堆上开辟,图标在窗口创建后就设置到QWidget,图标对象释本身放不释放不影响图标的显示。
QIcon不支持对象树机制,并不能设置父节点。
2.路径不要包含转义字符
路径分割符使用 1./ 2.\\
\\是为了防止单反斜杠被识别成转义字符出现歧义
3.C++11引入 row string来解决上述问题
字符串里不包含转义字符(任何字符都不会进行转义)
使用:r("d:\ret.jpg")
4.图片路径问题
因为无法确保开发主机的图片路径和用户图片路径不一致
建议使用相对路径,将图片保存到项目目录下
但相对路径这样的方式,还需要在打包文件的时候,将exe程序,和图片按照一定的目录结构,打包发送给用户
引入QRC机制
||
\\//
QRC机制
Qt提供QRC机制
从根本上解决问题1.保证用户机存在图片路径 2.保证图片不会被用户删掉
为Qt项目引入一个xml文件(后缀为.qrc),在这个xml文件中导入图片资源。
后续编译时,将xml的资源提取,转换成二进制数据,保存到程序代码中。
这样所以图片不会被用户删掉了,缺点无法导入太大的文件。
如视频文件。
使用QRC示例:

二进制数据用数组保存,Qt抽象出虚拟的目录,来方便访问图片。
1)创建"前缀"Prefix

改成/。
2)点击Add Files,添加图片资源

3)要求图片必须保存在qrc文件的同级目录下,或同级的子目录里

4)导入成功效果

5)使用该图片:
QIcon(":/image/icon.png")

效果:
查看图片资源生成的代码:
build目录下的,debug目录中,新增
