所谓 GUI 界面,归根结底,就是一堆组件的叠加。我们创建一个窗口,把按钮放上面,把图标放上面,这样就成了一个界面。在放置时,组件的位置尤其重要。我们必须要指定组件放在哪里,以便窗口能够按照我们需要的方式进行渲染。这就涉及到组件定位的机制。
Qt 提供了两种组件定位机制:绝对定位和布局定位。
绝对定位就是一种最原始的定位方法:给出这个组件的坐标和长宽值。
这样,Qt 就知道该把组件放在哪里以及如何设置组件的大小。但是这样做带来的一个问题是,如果用户改变了窗口大小,比如点击最大化按钮或者使用鼠标拖动窗口边缘,采用绝对定位的组件是不会有任何响应的。这也很自然,因为你并没有告诉 Qt,在窗口变化时,组件是否要更新自己以及如何更新。或者,还有更简单的方法:禁止用户改变窗口大小。但这总不是长远之计。
布局定位:你只要把组件放入某一种布局,布局由专门的布局管理器进行管理。当需要调整大小或者位置的时候,Qt 使用对应的布局管理器进行调整。
布局定位完美的解决了使用绝对定位的缺陷。
Qt 提供的布局中以下三种是我们最常用的:
QHBoxLayout
:按照水平方向从左到右布局;
QVBoxLayout
:按照竖直方向从上到下布局;
QGridLayout
:在一个网格中进行布局,类似于 HTML 的 table;
这4个为系统给我们提供的布局的控件,但是使用起来不是非常的灵活,这里就不详细介绍了。
第二种布局方式是利用控件里的widget来做布局,在Containers中
在widget中的控件可以进行水平、垂直、栅格布局等操作
实现一个我自己的登录退出窗口:
首先看效果:
几点说明:
其中的用户名和密码是由Label
和Line Edit
实现;
登录退出是由pushbutton
实现
在mainwindow.cpp
中添加代码将整个窗口的大小固定:
setFixedSize(500,400);//设置固定的窗口大小
在属性里的windowTitle
设置窗口的名称:
效果如下:
Qt为我们应用程序界面开发提供的一系列的控件,下面我们介绍两种最常用一些控件,所有控件的使用方法我们都可以通过帮助文档获取。
在pushbutton按钮里添加图标:
首先添加资源文件:
回顾一下添加资源文件的步骤:
1 在项目文件里创建一个资源文件res
2 在mainwindow.cpp里添加你想要使用的文件资源 如图片
3 在生成的res.qrc文件下添加前缀和文件即可
熟悉常用的几个按钮即可:
push button tool button radio button check box
以及 group box:起到把其他几个组成一组的作用 如性别 问卷调查 婚姻状况
看以下效果:
利用listWidget控件写诗:
添加代码a
//利用listWidget写诗
QListWidgetItem * item = new QListWidgetItem("悯农");
//将一行诗放入到listWidget控件中
ui->listWidget->addItem(item);
item->setTextAlignment(Qt::AlignHCenter);//居中设置
//将整首诗放入
QStringList list; //列表容器
list<<"锄禾日当午"<<"汗滴禾下土"<<"谁知盘中餐"<<"粒粒皆辛苦";
ui->listWidget->addItems(list);
熟悉树控件的使用
widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include
#include
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//treeWidget树控件使用
//设置水平头
ui->treeWidget->setHeaderLabels(QStringList()<<"书籍"<<"书籍分类");
QTreeWidgetItem * WenItem = new QTreeWidgetItem(QStringList()<<"文学");
QTreeWidgetItem * ZheItem = new QTreeWidgetItem(QStringList()<<"哲学");
QTreeWidgetItem * LiItem = new QTreeWidgetItem(QStringList()<<"历史");
//加载顶层的节点
ui->treeWidget->addTopLevelItem(WenItem);
//加载顶层的节点
ui->treeWidget->addTopLevelItem(ZheItem);
//加载顶层的节点
ui->treeWidget->addTopLevelItem(LiItem);
//追加子节点
QStringList book1,book2;
book1<<"小说"<<"小说分为长篇中篇和短篇";
book2<<"散文"<<"散文分为抒情散文和记叙散文";
QTreeWidgetItem * b1 = new QTreeWidgetItem(book1);
QTreeWidgetItem * b2 = new QTreeWidgetItem(book2);
WenItem->addChild(b1);
WenItem->addChild(b2);
QStringList book3,book4;
book3<<"马克思"<<"马克思是我知道的国外的最伟大的哲学家";
book4<<"毛泽东"<<"毛泽东主席是伟大的哲学家";
QTreeWidgetItem * b3 = new QTreeWidgetItem(book3);
QTreeWidgetItem * b4 = new QTreeWidgetItem(book4);
ZheItem->addChild(b3);
ZheItem->addChild(b4);
QStringList book5,book6;
book5<<"唐代"<<"唐朝的开国皇帝是唐高祖李渊";
book6<<"宋朝"<<"宋朝的开国皇帝是赵匡胤";
QTreeWidgetItem * b5 = new QTreeWidgetItem(book5);
QTreeWidgetItem * b6 = new QTreeWidgetItem(book6);
LiItem->addChild(b5);
LiItem->addChild(b6);
}
Widget::~Widget()
{
delete ui;
}
widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//TableWidget控件 事先在界面里拖入这个控件
//设置列数
ui->tableWidget->setColumnCount(3);
//设置水平表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄");
//设置行数
ui->tableWidget->setRowCount(4);
//设置正文
QStringList nameList;//创建一个容器保存姓名
nameList<<"刘能"<<"赵四"<<"谢广坤"<<"谢大脚";
QList<QString>sexList;//创建保存性别的容器
sexList<<"男"<<"男"<<"男"<<"女";
//for循环实现填充每一个表格
for(int i=0;i<4;i++)
{
int col=0;//固定一行 列数每次加一 开始遍历填充
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(nameList[i]));
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexList.at(i)));
//int 转 string
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+20)));
}
}
Widget::~Widget()
{
delete ui;
}
在搭建Qt窗口界面的时候,在一个项目中很多窗口,或者是窗口中的某个模块会被经常性的重复使用。一般遇到这种情况我们都会将这个窗口或者模块拿出来做成一个独立的窗口类,以备以后重复使用。
在项目文件下创建Qt设计师界面类
会生成单独的一个类和一个ui文件 ,我们在这里实现自定义的控件:
如下图:
那么这个SmallWidget
可以作为独立的窗口显示,也可以作为一个控件来使用:
打开Qt的.ui文件,因为SmallWidget相当于是子类
是派生自Qwidget相当于是父类
类,所以需要在ui文件中先放入一个QWidget控件, 然后再上边鼠标右键
实现最后的功能:
实现的功能一:左边数字和右边进度条同步增长
实现功能二:按“获取当前值按钮”
可以得到此时的数字
实现的功能三:不论进度条数值多少 按设置到一半 左右都归于50
代码实现
smallWidget.h
#ifndef SMALLWIDGET_H
#define SMALLWIDGET_H
#include
namespace Ui {
class SmallWidget;
}
class SmallWidget : public QWidget
{
Q_OBJECT
public:
explicit SmallWidget(QWidget *parent = nullptr);
~SmallWidget();
//设置数字 在头文件里进行函数声明
void setNum(int num);
//获取数字
int getNum();
private:
Ui::SmallWidget *ui;
};
#endif // SMALLWIDGET_H
smallWidget.cpp
#include "smallwidget.h"
#include "ui_smallwidget.h"
SmallWidget::SmallWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::SmallWidget)
{
ui->setupUi(this);
//实现以下功能
// QSpinBox移动 QSlider跟着一起移动
void(QSpinBox::* spSignal)(int)=&QSpinBox::valueChanged;
connect(ui->spinBox,spSignal,ui->horizontalSlider,&QSlider::setValue);
//QSlider移动 QSpinBox数字跟着一起改变
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
}
//设置数字
//在源文件里进行函数实现
void SmallWidget:: setNum(int num)
{
ui->spinBox->setValue(num);
};
//获取数字
int SmallWidget::getNum()
{
return ui->spinBox->value();
};
SmallWidget::~SmallWidget()
{
delete ui;
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//点击获取 获取当前控件的当前值
connect(ui->btn_get,&QPushButton::clicked,[=](){
qDebug()<<ui->widget_2->getNum();
});
//设置到一半
connect(ui->btn_set,&QPushButton::clicked,[=](){
ui->widget_2->setNum(50);
});
}
Widget::~Widget()
{
delete ui;
}