文章目录
- QWidget
- enabled
- geometry
- window frame
- windowTitle
- windowIcon
- qrc资源管理
- windowOpacity
- cursor
- font
- toolTip
- focusPolicy
- styleSheet
- 按钮类
- PushButton
- RadioButton
- CheckBox
- Signals
- 显示类
- Label
- LCDNumber
- ProgressBar
- Calendar
- 输入类
- LineEdit
- TextEdit
- ComboBox
- SpinBox
- DateTimeEdit
- Dial
- Slider
- 快捷键
- 多元素控件
- ListWidget
- TableWidget
- TreeWidget
- 容器类控件
- GroupBox
- TabWidget
- 布局管理器
- 垂直布局
- 水平布局
- 网格布局
- 表单布局
QWidget
所有控件的父类
enabled
API | Intro |
---|---|
isEnabled() | 返回控件是否可用,可用为true,不可用为false |
setEnable(bool) | 设置控件的可用状态,可用为true,不可用为false |
geometry
位置与尺寸,位置指的是控件在父控件中的坐标。
x
横坐标y
纵坐标width
宽度height
高度
API | Intro |
---|---|
geometry() | 获取到控件的位置和尺寸,返回结果是⼀个QRect |
setGeometry(QRect) | 使用QRect对象,设置控件的位置和尺寸 |
setGeometry(int x,int y, int width,int height) | 分四个属性设置控件的位置和尺寸 |
QRect
: 保存位置和尺寸的对象,包含了x, y, width, height,其中x, y是控件左上⻆的坐标。其接口setX()
, setY()
只是修改控件左上角点的坐标,width和height会随之改变。
示例:点击操控某个控件的尺寸不变,上下左右移动
void Widget::on_pushButton_up_clicked()
{
QRect rect = ui->target->geometry();
ui->target->setGeometry(rect.x(), rect.y()-20, rect.width(), rect.height());
}
void Widget::on_pushButton_down_clicked()
{
QRect rect = ui->target->geometry();
ui->target->setGeometry(rect.x(), rect.y()+20, rect.width(), rect.height());
}
void Widget::on_pushButton_left_clicked()
{
QRect rect = ui->target->geometry();
ui->target->setGeometry(rect.x()-20, rect.y(), rect.width(), rect.height());
}
void Widget::on_pushButton_right_clicked()
{
QRect rect = ui->target->geometry();
ui->target->setGeometry(rect.x()+20, rect.y(), rect.width(), rect.height());
}
window frame
- 如果widget作为⼀个窗⼝(带有标题栏,最⼩化,最⼤化,关闭按钮),那么在计算尺⼨和坐标的
时候就有两种算法.包含windowframe和不包含windowframe.- 其中x(),y(),frameGeometry(),pos(),move()都是按照包含windowframe的⽅式来计算
的.- 其中geometry(),width(),height(),rect(),size()则是按照不包含windowframe的⽅式来计
算的.- 当然,如果⼀个不是作为窗⼝的widget,上述两类⽅式得到的结果是⼀致的.
windowTitle
控件的窗口标题
API | Intro |
---|---|
windowTitle() | 获取控件的窗口标题 |
setWindowTitle(const QString& title) | 设置控件的窗口标题 |
上述设置操作针对不同的widget可能会有不同的⾏为。如果是顶层widget(独⽴窗⼝),这个操作才会有效。
windowIcon
控件的窗口图标
API | Intro |
---|---|
windowIcon() | 获取控件的窗口图标,返回QIcon 对象 |
setWindowIcon(const QIcon& icon) | 设置控件的窗口图标 |
同windowTitle,上述操作仅针对顶层widget有效
对于自定义图标,可用先创建一个QPixmap
对象,导入自定义图片(qrc),再用该对象创建QIcon
qrc资源管理
- 右键项⽬,创建⼀个QtResourceFile(qrc⽂件),⽂件名随意起(不要带中⽂),此处叫做resource.qrc。在qrc编辑器中,添加前缀,表示图片在Qt项目中的相对路径,供代码中使用。添加资源文件,添加的⽂件必须是在qrc⽂件的同级⽬录,或者同级目录的子目录。
- 将图片导入qrc后,在build构建目录中debug文件夹会生成一个
qrc_resource.cpp
文件,图片转化成cpp代码(一个保存二进制数据的数组)。最后项目编译时,会将这些代码编译到exe
文件中,后续⽆论exe
被复制到哪个⽬录下,都确保能够访问到该图片资源。
- 在Qt代码中使用来自qrc的资源
QPixmap pixmap(":/add.png");
:
表示从qrc中获取资源/
是在qrc中已添加的(虚拟 )资源文件目录前缀add.png
是资源文件名
qrc资源管理方案的优缺点
优点:确保了图⽚,字体,声⾳等资源能够真正做到"目录⽆关",⽆论如何都不会出现资源丢失的情况。
缺点:不适合管理体积⼤的资源。如果资源比较⼤(⽐如是⼏个MB的⽂件),或者资源特别多,⽣成的最终的exe体积就会⽐较⼤,程序运⾏消耗的内存也会增⼤,程序编译的时间也会显著增加。
windowOpacity
控件的透明度。但事实上是不透明的程度,用浮点数表示,数值越大,控件越不透明。
API | Intro |
---|---|
windowOpacity() | 获取到控件的不透明数值,返回float,取值为[0.0, 1.0]。其中0.0表示全透明,1.0表示完全不透明 |
setWindowOpacity(level) | 设置控件的不透明度,level最大值为1,大于1自动转换为1。 |
cursor
控件的悬停光标样式
API | Intro |
---|---|
cursor() | 获取当前控件的光标样式,返回QCursor对象 |
setCursor(const QCursor& cursor) | 设置控件的光标样式,仅在⿏标停留在该控件上时⽣效 |
QCursor
是表示光标样式的对象,可以使用Qt内置的,也可以自定义。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//使用内置光标
this->setCursor(Qt::WaitCursor);
//创建一个pixmap对象,加载自定义光标图像(来自qrc)
QPixmap pixmap(":/add.png");
//可以对pixmap进行缩放,scaled返回的是缩放后的图像副本
pixmap = pixmap.scaled(30, 30);
//通过pixmap创建一个cursor对象,可以设置热点(光标点击生效的点)坐标
QCursor cursor(pixmap, 15, 15);
//设置光标
ui->pushButton_add_opacity->setCursor(cursor);
}
font
字体属性
API | Intro |
---|---|
font() | 获取控件的字体信息,返回QFont对象 |
setFont() | 设置控件的字体信息 |
QFont
用于表示字体的各种属性信息。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
QLabel *label = new QLabel(this);
label->setText("Hello World!");
QFont font;
//设置字体家族
font.setFamily("Consola");
//设置字体大小
font.setPointSize(20);
//设置字体加粗
font.setBold(true);
//设置字体倾斜
font.setItalic(true);
//设置下划线
font.setUnderline(true);
//设置删除线
font.setStrikeOut(true);
//将字体信息设置到文本上
label->setFont(font);
}
toolTip
鼠标悬停在控件上时,提示用户一些信息(一般是该控件的功能、属性等)
API | Intro |
---|---|
setToolTip(const QString& ) | 设置toolTip,鼠标悬停时的提示说明 |
setToolTipDuration(int msec) | 提示的时间,单位是ms,时间一到toolTip自动消失 |
this->setToolTip("Hello");
this->setToolTipDuration(2000);
focusPolicy
控件获取到焦点的策略。控件获取到焦点意味着接下来的操作都对此控件进行(常用于多个输入栏的切换)。
API | Intro |
---|---|
focusPolicy() | 获取控件获取焦点的策略,返回Qt::FocusPolicy |
setFocusPolicy() | 设置控件获取焦点的策略 |
Qt::FocusPolicy
是Qt内置的枚举类型,取值如下:
namespace Qt{
//...
enum FocusPolicy {
NoFocus = 0, //不会获取焦点
TabFocus = 0x1, //控件可通过Tab键获取到焦点
ClickFocus = 0x2, //控件可通过鼠标点击获取到焦点
StrongFocus = TabFocus | ClickFocus | 0x8, //Tab和数据点击接受焦点(默认值)
WheelFocus = StrongFocus | 0x4 //类似于Qt::StrongFocus,同时控件也通过⿏标滚轮获取到焦点
};
}
//设置focusPolicy的方法
widget->setFocusPolicy(Qt::NoFocus);
styleSheet
层叠样式表 QSS
设置样式的格式——键值对
按钮类
按钮都继承自QAbstractButton
类,按钮的很多关键的属性都来自这个基类。
属性 (from QAbstractButton) | 说明 |
---|---|
text | 按钮中的文本 |
icon | 按钮中的图标 |
iconSize | 图标尺寸 |
shortCut | 按钮的快捷键 |
autoRepeat (true or false) | 按钮是否会重复触发,即鼠标左键按住不放时,是否“连发” |
autoRepeatDelay | 重复触发的延时时间,即按住按钮多久后,开始“连发” |
autoRepeatInterval | 重复触发的周期 |
checkable | 是否可被选中 |
checked | 是否已被选中,checkable是checked的前提条件 |
PushButton
设置按钮的快捷键
void setShortcut(const QKeySequence &key);
QKeySequence
:用于保存快捷键序列的对象,因为快捷键可以是单个,也可以是多个键的组合。对于QKeySequence
对象的构造,可用表示按键的字符串,如QKeySequence("w")
;也可用Qt内置的表示按键的宏,如下:
ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_Up));//单个快捷键
ui->pushButton_up->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up));//组合快捷键
按钮设置快捷键后,按下一次快捷键,发出的信号是
clicked
(按下了就触发,而不是按下后释放再触发),相当于鼠标点击一次按钮(press + released)。所以当你按住快捷键时,是会重复触发clicked
的(不停在按下)。
样例:上下左右方向键,控制飞机的移动
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QIcon icon(":/image/plane.png");
ui->plane->setIcon(icon);//设置飞机图标
ui->plane->setIconSize(QSize(50, 50));//设置图标尺寸
//设置方向键图标
ui->pushButton_up->setIcon(QIcon(":/image/up.png"));
ui->pushButton_down->setIcon(QIcon(":/image/down.png"));
ui->pushButton_left->setIcon(QIcon(":/image/left.png"));
ui->pushButton_right->setIcon(QIcon(":/image/right.png"));
//设置方向键快捷键
ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_Up));//组合快捷键
ui->pushButton_down->setShortcut(QKeySequence(Qt::Key_Down));
ui->pushButton_left->setShortcut(QKeySequence(Qt::Key_Left));
ui->pushButton_right->setShortcut(QKeySequence(Qt::Key_Right));
//开启重复触发
ui->pushButton_up->setAutoRepeat(true);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_up_clicked()
{
QRect rect = ui->plane->geometry();
ui->plane->setGeometry(rect.x(), rect.y() - 5, rect.width(), rect.height());
}
void Widget::on_pushButton_down_clicked()
{
QRect rect = ui->plane->geometry();
ui->plane->setGeometry(rect.x(), rect.y() + 5, rect.width(), rect.height());
}
void Widget::on_pushButton_left_clicked()
{
QRect rect = ui->plane->geometry();
ui->plane->setGeometry(rect.x() - 5, rect.y(), rect.width(), rect.height());
}
void Widget::on_pushButton_right_clicked()
{
QRect rect = ui->plane->geometry();
ui->plane->setGeometry(rect.x() + 5, rect.y(), rect.width(), rect.height());
}
RadioButton
QRadioButton
单选按钮,按钮之间具有“排他性”,即一组单选按钮中只能选中其中一个。
QAbstractButton
中与QRadioButton
较为相关的属性
属性 | 说明 |
---|---|
checkable | 是否可被选中 |
checked | 是否已被选中,checkable是checked的前提条件 |
autoExclusive | 是否“排他”,对于QRadioButton默认是“排他”的 |
通常情况下需要为RadioButton分组,以满足不同分类的选择,否则整个页面的单选按钮都有“排他性”,因为它们默认在一个组内。如下是一个简单的点餐菜单,我们想要实现的是每个类型中的选择唯一性,因此必须进行分组。
Qt中提供了QButtonGroup
类以实现按钮的分组
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//创建按钮组
QButtonGroup* groupStaple = new QButtonGroup(this);
QButtonGroup* groupDrink = new QButtonGroup(this);
QButtonGroup* groupSnack = new QButtonGroup(this);
//为按钮组添加按钮
groupStaple->addButton(ui->radioButton);
groupStaple->addButton(ui->radioButton_2);
groupStaple->addButton(ui->radioButton_3);
groupDrink->addButton(ui->radioButton_5);
groupDrink->addButton(ui->radioButton_6);
groupDrink->addButton(ui->radioButton_7);
groupSnack->addButton(ui->radioButton_8);
groupSnack->addButton(ui->radioButton_9);
}
“排他性”意味着用户无法多选或取消选中,若想要取消选中,要先暂时地取消“排他性”。如下示例,点餐(这里只点了主食)提交后,实现重置(清除)所有选中。
void Widget::on_pushButton_clicked()
{
QButtonGroup* groupStaple = findChild<QButtonGroup*>("groupStaple");//获取按钮组
if (groupStaple)
{
QList<QAbstractButton*> buttons = groupStaple->buttons();
groupStaple->setExclusive(false); // 取消排他性 (按钮组的排他性,决定该组中的按钮之间是否互斥)
foreach(QAbstractButton *button, buttons)//遍历groupStaple中所有单选按钮
{
button->setChecked(false);// 取消groupStaple中所有单选按钮的选中状态
}
groupStaple->setExclusive(true); // 恢复排他性
}
else
{
qDebug() << "groupStaple not found";
}
}
CheckBox
QCheckBox
复选按钮,支持多选,和 QCheckBox
最相关的属性也是 checkable
和 checked
, 都是继承⾃QAbstractButton
Signals
clicked有带参数和不带参数的两种类型:
-
clicked():点击“按钮”(按下+释放),不提供按钮状态信息。
-
clicked(bool checked):适用于可切换按钮,提供按钮的选中状态信息。
-
pressed():“按下”按钮
-
released(): “释放”按钮
-
toggled(bool checked): 按钮状态切换时
示例:
void Widget::on_checkBox_clicked(bool checked)
{
//复选按钮被选中时 checked == true
//复选按钮取消选中时 checked == false
qDebug() << "clicked(bool)" << checked;
}
void Widget::on_radioButton_4_toggled(bool checked)
{
//切换状态时触发:
//被选中 checked == true
//未选中 checked == false
qDebug() << "toggled(bool)" << checked;
}
显示类
Label
Qlabel
可以显示文字和图片
文本格式
QLabel属性 | 说明 |
---|---|
text | Qlabel 中的文本 |
textFormat | 文本的格式:纯文本、富文本、markdown,通过Qt自带的宏设置 |
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->label->setText("<b>这是一段文本</b>");
ui->label->setTextFormat(Qt::PlainText);//纯文本
ui->label_2->setText("<b>这是一段文本</b>");
ui->label_2->setTextFormat(Qt::RichText);//富文本
ui->label_3->setText("# 这是一段文本");
ui->label_3->setTextFormat(Qt::MarkdownText);//markdown
ui->label_4->setText("<i>这是一段文本</i>");
ui->label_4->setTextFormat(Qt::AutoText);//根据文本内容自动决定格式
}
设置图片
属性 | 说明 |
---|---|
pixmap | label中的图片 (QPixmap ) |
scaledContents | 设为true表示自动拉伸内容(仅对图片有效),填充Qlabel ;设为false则不会自动拉伸 |
ui->label_image->setPixmap(QPixmap(":/cat.png"));//设置QLabel的图片
ui->label_image->setScaledContents(true);//自动伸缩填满QLabel
文本控制(对齐、自动换行、缩进、边距)
属性 | 说明 |
---|---|
alignment | 对齐方式,由Qt内置宏提供,可以选中一种对齐方式,也可以多种组合 |
wordWrap | 设为 true 内部的文本会自动换行,防止文本长度过长,设为 false不会自动换行 |
indent | 设置文本缩进,水平和垂直方向都生效 |
margin | 内部⽂本和Qlabel边框之间的边距,上下左右四个方向同时生效 |
伙伴
属性 | 说明 |
---|---|
buddy | 给 QLabel 关联⼀个 “伙伴” , 这样触发QLabel时就能激活对应的伙伴,这里的“触发”一般是为QLabel设置一个快捷键 |
ui->label_buddy->setText("快捷键: &A");//QLabel文本中,'&'后的字符被定义为该QLabel的快捷键
ui->label_buddy->setBuddy(ui->radioButton);//将QLabel设置为单选按钮的伙伴
用户通过alt + 快捷键
来触发QLabel,从而激活对应的伙伴。
LCDNumber
QLCDNumber
显示数字,效果类似于“老式计算器”。
QLCDNumber
的主要属性
属性 | 说明 |
---|---|
intValue | 显示数字的数值 (int整型) |
value | 显示数字的数值 (double浮点型),intValue和value存在联系,如value设为3.14,intValue就是3。 |
digitCount | 显示几位数字(从右往左,少的显示空格) |
mode | 显示数字的进制:十进制、十六进制、二进制、八进制。只有十进制能显示小数点后的数字 |
segmentStyle | 设置显示的风格 |
注:与以往不同,对于intValue和value的设置,api是display()
(重载了int, double和QString三种类型参数的设置),而不是setintValue()
和setValue()
。
例:用QLCDNumber
设计一个倒计时
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置初始值
ui->lcdNumber->display(5);
//创建一个定时器
QTimer* timer = new QTimer(this);
//将定时器的 timeout信号 绑定一个槽函数
connect(timer, &QTimer::timeout, this, [this, timer](){
//获取lcdNumber上的数字
int value = this->ui->lcdNumber->intValue();
if(value <= 0){
//倒计时结束
timer->stop();
return;
}
this->ui->lcdNumber->display(value - 1);
});
//启动计时器,设置触发timeout的周期(单位是毫秒)
timer->start(1000);
}
QTimer
是Qt中提供的一个定时器。在GUI编程中,很多场景会用到计时的功能(如倒计时、进度条等),一般来说可以创建一个异步线程,结合sleep()
接口,以实现计时功能。
但在Qt中又规定,Qt的界面由主线程维护,不允许其它线程对界面进行操作,以保证线程安全。因此,为了满足计时功能的需求,Qt提供了QTimer
,其工作机制是:每个一段时间间隔interval,就发出一次timeout
信号,它只负责计时,不负责实现“时间到”之后的具体逻辑。用户可以自定义interval和绑定槽函数,以实现不同的计时需求。而信号槽机制中,默认都是由主界面接收并处理信号,这样一来便很好地满足了GUI中的计时需求。
QTimer的主要接口
API | 说明 |
---|---|
start(int msec) | 启动计时器,并设置触发timeout的周期(单位是毫秒) |
stop() | 停止计时器 |
ProgressBar
QProgressBar
进度条
QProgressBar
的主要属性
属性 | 说明 |
---|---|
minimum | 进度条最小值 |
maximum | 进度条最大值 |
value | 进度条当前值 |
format | 展示数字的格式:%p 百分比、%v 数值、%m 剩余时间(毫秒)、%t 总时间(毫秒) |
例:进度条走完,关闭窗口
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
int min = ui->progressBar->minimum();
int max = ui->progressBar->maximum();
ui->progressBar->setValue(min);
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [=](){
int value = ui->progressBar->value();
if(value >= max){
timer->stop();
this->close();
return;
}
ui->progressBar->setValue(value + 1);
});
timer->start(100);
}
QProgressBar
和QLCDNumber
相同,往往需要和定时器QTimer
搭配使用。
使用QSS改变进度条的颜色:
Calendar
QCalendarWidget
是Qt中的日历控件
QCalendarWidget
的主要属性
属性 | 说明 |
---|---|
selectDate | 当前选中的日期(QDate ) |
dateEditEnabled | 日期是否允许被编辑 (bool ) |
minimumDate | 最大日期(QDate ) |
maximumDate | 最小日期(QDate ) |
QCalendarWidget
的主要信号
信号 | 说明 |
---|---|
selectionChanged(const QDate&) | 当选中的⽇期发⽣改变时发出 |
activated(constQDate&) | 当双击⼀个有效的⽇期或者按下回⻋键时发出,形参是⼀个QDate类型,保存 了选中的⽇期 |
currentPageChanged(int, int) | 当年份⽉份改变时发出,形参表⽰改变后的新年份和⽉份 |
输入类
LineEdit
QLineEdit
是单行输入框,可以输入一行文本,不能换行。
QLineEdit
的主要属性
属性 | 说明 |
---|---|
text | 输入框中的文本 |
inputMask | 输入内容的格式约束 (QString ) |
maxLength | 最大文本长度 |
echoMode | 显示方式:1.QLineEdit::Normal 2.QLineEdit::Password 3.QLineEdit::NoEcho |
readOnly | 是否为只读 (bool ) |
placeHolderText | 当输入框为空时的显示信息,一般作为提示 |
clearButtonEnabled | 当输入框不为空时,是否会显示清除按钮 (bool ) |
QLineEdit
的主要信号
信号 | 说明 |
---|---|
void textChanged(const QString& text) | 当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。 代码对⽂本的修改能够触发这个信号 |
void textEdited(const QString& text) | 当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。 代码对⽂本的修改不能触发这个信号 |
-
输入内容的格式约束
inputMask可以实现输入内容的格式约束
ui->lineEdit_phone->setInputMask("000-0000-0000");//其中'0'代表数字
但在实际开发中,通常采用“正则表达式”来实现格式约束,Qt中提供验证器
QValidator
,其派生类QRegExpValidator
为正则验证器,我们可以为QLineEdit
设置一个正则验证器,以验证输入栏中的内容是否符合预期格式。例:学生输入学号,只有当输入学号合法时,才允许提交
#include "widget.h" #include "ui_widget.h" #include <QRegExpValidator> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); ui->pushButton_submit->setEnabled(false);//当输入学号合法时,才允许提交 ui->lineEdit_id->setPlaceholderText("请输入学号: 入学年份-学院号-个人号"); ui->lineEdit_id->setClearButtonEnabled(true); //为lineEdit_id注册一个正则验证器,并为验证其设置正则表达式 ui->lineEdit_id->setValidator(new QRegExpValidator(QRegExp("^20\\d{2}\\d{3}\\d{3}$"))); //该正则表达式的含义 //入学年份4位,且必须以 20 开头 //学院号3位 //个人号3位 } void Widget::on_lineEdit_id_textEdited(const QString &arg1) { QString id = arg1; int pos = 0; //验证新输入学号的是否符合正则表达式的格式 if(ui->lineEdit_id->validator()->validate(id, pos) == QValidator::Acceptable){ //符合 ui->pushButton_submit->setEnabled(true); } else{ //不符合 ui->pushButton_submit->setEnabled(false); } } void Widget::on_pushButton_submit_clicked() { qDebug() << ui->lineEdit_id->text(); }
TextEdit
QTextEdit
是多行输入框,可以输入多行文本。
主要属性
属性 | 说明 |
---|---|
markdown | 输入框中的内容支持markdown格式 |
html | 输入框中的内容支持html格式 |
placeHolderText | 当输入框为空时的显示信息,一般作为提示 |
undoRedoEnable | 是否触发 undo (ctrl + z) / redo (ctrl + y) 功能 |
verticalScrollBarPolicy | 垂直方向滚动条的出现策略,默认根据内容⾃动决定是否需要滚动条 |
horizontalScrollBarPolicy | 水平方向滚动条的出现策略,默认根据内容⾃动决定是否需要滚动条 |
主要方法
接口 | 说明 |
---|---|
QString toHtml() | 以html 格式获取输入框中的文本 |
QString toMarkdown() | 以markdown 格式获取输入框中的文本 |
void setHtml(const QString &text) | 设置输入框中的内容为一段html 格式的文本,并且此后输入都是这种格式 |
void setMarkdown(const QString &text) | 设置输入框中的内容为一段markdown 格式的文本,并且此后输入都是这种格式 |
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->label->setTextFormat(Qt::MarkdownText);
ui->pushButton->setText("转化为html");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_textEdit_textChanged()
{
ui->label->setText(ui->textEdit->toMarkdown());
}
void Widget::on_pushButton_clicked()
{
ui->textEdit->setHtml("<b>你好</b>");
}
输入markdown格式文本,在label中渲染成markdown
转化为html后,再输入的内容都是预设的<b></b>
格式。
主要信号
信号 | 触发时机 |
---|---|
textChanged | 输入框内容发生改变时 |
selectionChanged() | 选中的文本发生改变时 |
cursorPositionChanged() | 光标的位置发生改变时 |
undoAvailable(bool) | undo功能可用状态切换时(内容不为空,undo就可用) |
redoAvailable(bool) | redo功能可用状态切换时(undo之后,redo就可用) |
copyAvaiable(bool) | ⽂本被选中/取消选中时触发 |
QTextCursor
表示文本光标,可获取选中的文本、光标的位置。通常和selectionChanged
,cursorPositionChanged
信号搭配使用。
void Widget::on_textEdit_selectionChanged()
{
QTextCursor cursor = ui->textEdit->textCursor();//获取textEdit的光标
ui->label->setText(cursor.selectedText());//获取被选中的文本
}
void Widget::on_textEdit_cursorPositionChanged()
{
QTextCursor cursor = ui->textEdit->textCursor();//获取textEdit的光标
qDebug() << "cursorPositionChanged()" << cursor.position();//获取光标位置
}
ComboBox
QComboBox
下拉列表,多个选项供用户选择
主要属性
属性 | 说明 |
---|---|
currentText | 当前选中条目的文本 |
currentIndex | 当前选中条目的下标(从0开始,无选中条目则为-1) |
editable | 是否可编辑 |
iconSize | 下拉框图标(小三角)的大小 |
maxCount | 条目最大个数 |
主要方法
接口 | 说明 |
---|---|
addItem(const QString& ) | 添加条目 |
currentText() | 获取当前选中条目的文本 |
currentIndex() | 获取当前选中条目的下标 |
setEditable(bool) | 设置是否可编辑 |
若editable
设为true
, 用户确认编辑的条目后, 若该条目不存在, 则添加这个条目
ui->comboBox->addItem("战士");
ui->comboBox->addItem("法师");
ui->comboBox->addItem("坦克");
ui->comboBox->setEditable(true);//设下拉列表为可编辑
主要信号
信号 | 说明 |
---|---|
currentIndexChanged(int) | 当前条目下标改变时触发, 传入参数为改变后的条目下标 |
currentIndexChanged(QString) | 当前条目下标改变时触发, 传入参数为改变后的条目文本 |
currentTextChanged(QString) | 当前条目文本改变时触发, 传入参数为改变后的条目文本 |
activated(int) / activated(QString) | 用户选中一个条目时触发 (不管该条目是否已选中) |
SpinBox
QSpinBox
微调框,对数字进行微调。QSpinBox
针对整型,QDoubleSpinBox
针对浮点数,用法基本相同。
主要属性
属性 | 说明 |
---|---|
value | 当前值 |
singleStep | 单次调整的步长 |
displayInterger | 数字的进制。例如displayInteger设为10,则是按照十进制表示,设为2则为二进制表示 |
minimum | 最小值 |
maximum | 最大值 |
suffix | 后缀 |
prefix | 前缀 |
setRange(int min, int max)
可以调整最大值和最小值,即修改微调框可变的数值范围。
主要信号
信号 | 触发时机 |
---|---|
valueChanged(int) | 微调框的⽂本发⽣改变时触发,参数int表示当前的数值. |
textChanged(QString) | 微调框的⽂本发⽣改变时触发,参数QString带有前缀和后缀 |
DateTimeEdit
QDateTimeEdit
编辑日期与时间
主要属性
属性 | 说明 |
---|---|
dateTime | 日期时间的值 (QDateTime ) |
date | 日期 (QDate ) |
time | 时间 (QTime ) |
displayFormat | 时间日期格式。形如 yyyy/M/d H:mm |
minimumDateTime | 最小日期时间 |
maximumDateTime | 最大日期时间 |
timeSpec | Qt::LocalTime :本地时间;Qt::UTC :显⽰协调世界时(UTC);Qt::OffsetFromUTC :显⽰相对于UTC的偏移量(时差) |
setDateTimeRange(const QDateTime &min, const QDateTime &max)//设置日期时间的范围
-
关于
QDateTime
Qt中用于表示日期时间的类是
QDateTime
,以下是QDateTime
一些常用的接口,方便我们对日期时间进行操作接口 说明 daysTo(const QDateTime &other) 从this到other之间的天数。但有时会不符合预期,比如 2024/1/1 23:55 - 2024/1/2 0:05
也会被算成一天。secsTo(const QDateTime &other) 从this到other之间的秒数。 QString toString(const QString &format) 将日期时间转化成字符串,format是日期时间的字符串格式。
样例:日期计算器,计算两个日期之间的差值(几天几时)
#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_calc_clicked()
{
//1.获取两个前后两个日期时间
QDateTime former = ui->dateTimeEdit_former->dateTime();
QDateTime later = ui->dateTimeEdit_later->dateTime();
//2.计算两个日期时间差值
int secs = former.secsTo(later);
int days = secs / (3600 * 24);//总秒数 / 一天的秒数
int hours = (secs / 3600) % 24;// 总秒数/一小时的秒数 = 总小时数
ui->label_ret->setText(QString::number(days) + "天" + QString::number(hours) + "时");
}
void Widget::on_dateTimeEdit_later_dateTimeChanged(const QDateTime &later)
{
//确保第一个时间在第二个时间之前
QDateTime former = ui->dateTimeEdit_former->dateTime();
if(later < former){
ui->dateTimeEdit_former->setDateTime(later);
ui->dateTimeEdit_later->setDateTime(former);
}
}
Dial
QDial
表示一个旋钮,通过旋转改变数值
Slider
QSlider
表示一个滑动条,通过滑动改变数值
快捷键
Qt中基于信号槽机制,提供了一种通用的设置快捷键的方法。QShortcut
表示快捷键,用户可使用该类自定义快捷键。当相应的快捷键被激活时,触发QShortcut
的信号activated
,用户可自定义槽函数,完成快捷键被激活后的特定工作。
样例:设置快捷键-
和=
控制旋钮,旋钮的功能是控制窗口的透明度
#include "widget.h"
#include "ui_widget.h"
#include <QShortcut>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//1.设置旋钮的属性
ui->dial->setRange(0, 100);//旋钮数值范围(透明度范围)
ui->dial->setValue(100);//旋钮初始值
ui->dial->setWrapping(true);//允许循环转动
ui->dial->setNotchesVisible(true);//显示刻度线
//2.设置快捷键
QShortcut* shortcutSub = new QShortcut(this);
shortcutSub->setKey(QKeySequence("-"));
QShortcut* shortcutAdd = new QShortcut(this);
shortcutAdd->setKey(QKeySequence("="));
//3.绑定快捷键的“激活”信号和槽函数
connect(shortcutSub, &QShortcut::activated, this, [=](){
if(this->ui->dial->value() > 0){
this->ui->dial->setValue(this->ui->dial->value() - 5);
}
});
connect(shortcutAdd, &QShortcut::activated, this, [=](){
if(this->ui->dial->value() < 100){
this->ui->dial->setValue(this->ui->dial->value() + 5);
}
});
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_dial_valueChanged(int value)
{
this->setWindowOpacity(value / 100.0);
}
多元素控件
ListWidget
QListWidget
是一个纵向列表
主要属性
属性 | 说明 |
---|---|
currentRow | 当前被选中的是第几行(行的下标从0开始),若无选中,返回-1 |
count | 一共有多少行 |
sortingEnabled | 列表是否允许排序(若是,默认升序,可通过sortItems 修改排序方式) |
主要方法
接口 | 说明 |
---|---|
void addItem(const QString &label) void addItem(QListWidgetItem *item) | 添加列表元素 |
void insertItem(int row, QListWidgetItem *item) void insertItem(int row, const QString &label) | 在指定位置插入元素 |
QListWidgetItem *currentItem() int currentRow() | 返回当前选中的元素(指针或下标) |
QListWidgetItem * takeItem(int row) | 删除并返回指定行的元素 |
QListWidgetItem * item(int row) | 返回指定行的元素 |
void setCurrentItem(QListWidgetItem *item) void setCurrentRow(int row) | 设置选中的元素(使用指针或下标) |
注意,多元素控件QListWidget
中,对于某一个元素,可以用行表示,也可以用QListWidgetItem
指针表示。
QListWidgetItem
是表示QListWidget
中一个元素的类,本质是设置元素中的文本和图标,以及字体样式等。
样例:根据输入内容,新增列表的元素;删除指定列表中元素
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->lineEdit->setClearButtonEnabled(true);
ui->listWidget->setSortingEnabled(true);
ui->listWidget->addItem(new QListWidgetItem("初始"));//使用QListWidgetItem类添加元素
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_add_clicked()
{
const QString& text = ui->lineEdit->text();
if(!text.isEmpty()){
ui->listWidget->addItem(text);
}
}
void Widget::on_pushButton_del_clicked()
{
qDebug() << ui->listWidget->currentItem()->text();//获取选中元素的文本
int row = ui->listWidget->currentRow();
if(row >= 0){
ui->listWidget->takeItem(row);
}
}
主要信号
信号 | 触发时机 |
---|---|
currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) | 选中元素发生变化时(current变化后元素,previous变化前元素) |
currentRowChanged(int currentRow) | 选中元素发生变化时(currentRow当前行) |
itemClicked(QListWidgetItem*item) | 点击某个元素时触发 |
void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
if(current)
qDebug() << "当前元素:" << current->text();
if(previous) //若没有变化前没有选中元素,previous为nullptr
qDebug() << "最近元素:" << previous->text();
}
TableWidget
QTableWidget
是一个表格控件
主要属性
属性 | 说明 |
---|---|
columnCount | 列数 |
rowCount | 行数 |
主要方法
方法 | 说明 |
---|---|
QTableWidgetItem * item(int row, int column) | 根据行和列获取表格中某一元素 |
void setItem(int row, int column, QTableWidgetItem *item) | 根据行和列设置表格中某一元素 |
QTableWidgetItem * currentItem() | 返回被选中的元素 |
int currentRow() const | 返回被选中元素的行 |
int currentColumn() const | 返回被选中元素的列 |
setColumnCount(int) | 设置表格列数 |
setRowCount(int) | 设置表格行数 |
void setHorizontalHeaderItem(int column, QTableWidgetItem *item) | 设置列表头 |
void setVerticalHeaderItem(int column, QTableWidgetItem *item) | 设置行表头 |
void insertRow(int row) | 在指定位置插入新行 |
void insertColumn(int row) | 在指定位置插入新列 |
void removeRow(int row) | 删除指定行 |
void removeColumn(int column) | 删除指定列 |
和QListWidget
相同,在QTableWidget
中,对于某一个元素,可以用行和列表示,也可以用QTableWidgetItem
指针表示。而QTableWidgetItem
除了设置文本图标样式,还有两个特殊的方法,可以获取元素所在单元格的行和列
QTableWidgetItem::方法 | 说明 |
---|---|
row() | 获取元素所在单元格的行 |
column() | 获取元素所在单元格的列 |
样例:通过输入内容,确定新增行或列,以及对应表头
void Widget::on_pushButton_row_clicked()
{
int row = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(row);
const QString& header = ui->lineEdit_row->text();
if(!header.isEmpty()){
ui->tableWidget->setVerticalHeaderItem(row, new QTableWidgetItem(header));
}
}
void Widget::on_pushButton_col_clicked()
{
int col = ui->tableWidget->columnCount();
ui->tableWidget->insertColumn(col);
const QString& header = ui->lineEdit_col->text();
if(!header.isEmpty()){
ui->tableWidget->setHorizontalHeaderItem(col, new QTableWidgetItem(header));
}
}
主要信号
信号 | 触发时机 |
---|---|
cellClicked(int row,int column) | 点击单元格时 |
currentCellChanged(int row,int column,int previousRow,int previousColumn) | 选中单元格切换时 |
cellEntered(int row,int column) | ⿏标进⼊单元格时 |
TreeWidget
QTreeWidget
是一个树形控件,类似于操作系统中的目录结构。QTreeWidget
最上层没有根节点,而是由一系列的顶层节点(TopLevelItem)构成,然后再给顶层节点添加子节点,如此往复,最终形成树状结构。
QTreeWidget
里的每个元素,都是⼀个 QTreeWidgetItem
,每个QTreeWidgetItem
可以包含多个⽂本和图标,每个⽂本/图标为⼀个列
样例:
void Widget::on_pushButton_topLevel_clicked()
{
const QString& text = ui->lineEdit->text();
if(!text.isEmpty()){
QTreeWidgetItem* newItem = new QTreeWidgetItem();
if(newItem){
newItem->setText(0, text);
ui->treeWidget->addTopLevelItem(newItem);
}
}
// 可以不显式地为新创建的 QTreeWidgetItem 对象设置 parent 指针
// 因为 addTopLevelItem 会自动将 newItem 的父指针设置为 treeWidget
}
void Widget::on_pushButton_cur_clicked()
{
const QString& text = ui->lineEdit->text();
if(!text.isEmpty()){
QTreeWidgetItem* newItem = new QTreeWidgetItem();
if(newItem){
newItem->setText(0, text);
ui->treeWidget->currentItem()->addChild(newItem);
}
}
}
void Widget::on_pushButton_del_clicked()
{
QTreeWidgetItem* cur = ui->treeWidget->currentItem();
QTreeWidgetItem* parent = cur->parent();
if(parent == nullptr){
//顶层节点
int index = ui->treeWidget->indexOfTopLevelItem(cur);
ui->treeWidget->takeTopLevelItem(index);
}
else{
//非顶层节点
parent->removeChild(cur);
}
}
容器类控件
GroupBox
使⽤ QGroupBox
实现⼀个带有标题的分组框,可以把其他的控件放到里面作为⼀组,这样看起来能更好看⼀点。
TabWidget
QTabWidget
实现一个带有标签页的控件,可以往标签页中设置新的widget,以实现通过切换标签页在不同的widget中跳转。注意,标签页的内容是设置在另外创建的QWidget
对象中,QTabWidget
只是提供标签页。
主要属性
属性 | 说明 |
---|---|
tabPosition | 标签所在位置 North 上方South 下方West 左侧East 右侧 |
currentIndex | 当前选中标签页的下标(从0开始) |
currentTabText | 当前选中标签页的文本 |
tabsCloseable | 标签页是否可以关闭 |
movable | 标签页是否可以移动 |
主要方法
方法 | 说明 |
---|---|
int addTab(QWidget *page, const QString &label) | 添加一个新的标签页,page是标签页本体,label是标签页的选项卡文本。返回值是新标签页的编号。 |
int count() | 获取标签页的数量 |
void setCurrentWidget(QWidget *widget) | 通过QWidget 指针,设置当前标签页 |
void setCurrentIndex(int index) | 通过标签页编号,设置当前标签页 |
void removeTab(int index) | 根据标签页编号,删除标签页 |
主要信号
信号 | 触发时机 |
---|---|
currentChanged(int) | 标签页切换时,参数为切换后的标签页编号 |
tabBarClicked(int) | 点击选项卡的标签条的时候,参数为被点击的选项卡编号 |
tabCloseRequest(int) | tabsCloseable == true时,点击关闭标签页按钮触发,参数为被关闭的标签页编号 |
样例:实现新增标签页按钮,和点击标签页关闭按钮关闭标签页
#include "widget.h"
#include "ui_widget.h"
#include <QLabel>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->tabWidget->setTabsClosable(true);
QLabel* label = new QLabel(ui->tab);
label->setText("这是第一个标签页");
label->resize(150,60);
QLabel* label_2 = new QLabel(ui->tab_2);
label_2->setText("这是第二个标签页");
label_2->resize(150,60);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
//创建新标签页的Widget,还有标签页文本
QWidget* page = new QWidget();
int idx = ui->tabWidget->count() + 1;
ui->tabWidget->addTab(page, "Tab" + QString::number(idx));
//每次创建一个新标签页,自动选中它
ui->tabWidget->setCurrentWidget(page);
}
void Widget::on_tabWidget_tabCloseRequested(int index)
{
ui->tabWidget->removeTab(index);
}
布局管理器
垂直布局
QVBoxLayout
是垂直布局管理器。下面是设置垂直布局管理器的demo。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QVBoxLayout* layout = new QVBoxLayout();//创建一个垂直布局管理器
this->setLayout(layout);//将layout设置为窗口的布局管理器
layout->setContentsMargins(10,20,10,20);//设置布局的左、上、右、下间距
layout->setSpacing(50);//设置相邻元素的间距
//新建一些按钮
QPushButton* button1 = new QPushButton("按钮1");
QPushButton* button2 = new QPushButton("按钮2");
QPushButton* button3 = new QPushButton("按钮3");
//将按钮添加到布局管理器中
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
}
水平布局
QHBoxLayout
水平布局管理器。下面是设置垂直布局管理器的demo。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QHBoxLayout* layout = new QHBoxLayout();//创建一个垂直布局管理器
this->setLayout(layout);//将layout设置为窗口的布局管理器
layout->setContentsMargins(10,20,10,20);//设置布局的左、上、右、下间距
layout->setSpacing(50);//设置相邻元素的间距
//新建一些按钮
QPushButton* button1 = new QPushButton("按钮1");
QPushButton* button2 = new QPushButton("按钮2");
QPushButton* button3 = new QPushButton("按钮3");
//将按钮添加到布局管理器中
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
//设置拉伸系数,即在布局中所占的权重
layout->setStretch(0, 1);
layout->setStretch(1, 1);
layout->setStretch(2, 2);
}
每个控件(QWidget)只能有一个布局管理器(layout),在QtDesigner中在控件上创建多个layout,实际上内部为每个layout都新建了一个QWidget,再在新建的QWidget上设置layout。如果我们想在一个控件上创建多个layout,可以通过嵌套的方式实现。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QVBoxLayout* vlayout = new QVBoxLayout();//创建一个垂直布局管理器vlayout
this->setLayout(vlayout);//将vlayout设置为窗口的布局管理器
//新建一些按钮
QPushButton* button1 = new QPushButton("按钮1");
QPushButton* button2 = new QPushButton("按钮2");
QPushButton* button3 = new QPushButton("按钮3");
QPushButton* button4 = new QPushButton("按钮4");
//新建水平布局
QHBoxLayout* hlayout = new QHBoxLayout();
hlayout->addWidget(button3);
hlayout->addWidget(button4);
//将按钮添加到布局管理器中
vlayout->addWidget(button1);
vlayout->addWidget(button2);
//将水平布局嵌套到垂直布局中
vlayout->addLayout(hlayout);
}
网格布局
QGridLayout
是网格布局,实现m * n的二维网格布局效果。
void addWidget(QWidget *, int row, int column)//在网格布局中添加控件
demo
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QGridLayout* glayout = new QGridLayout();//创建网格布局,视为2行3列
this->setLayout(glayout);
QPushButton* btn1 = new QPushButton("按钮1");
QPushButton* btn2 = new QPushButton("按钮2");
QPushButton* btn3 = new QPushButton("按钮3");
QPushButton* btn4 = new QPushButton("按钮4");
QPushButton* btn5 = new QPushButton("按钮5");
QPushButton* btn6 = new QPushButton("按钮6");
glayout->addWidget(btn1, 0, 0);
glayout->addWidget(btn2, 0, 1);
glayout->addWidget(btn3, 0, 2);
glayout->addWidget(btn4, 1, 0);
glayout->addWidget(btn5, 1, 1);
glayout->addWidget(btn6, 1, 2);
//设置列的拉伸系数
glayout->setColumnStretch(0,1);
glayout->setColumnStretch(1,2);
glayout->setColumnStretch(2,1);
//设置行的拉伸系数
glayout->setRowStretch(0, 1);
glayout->setRowStretch(1, 2);
}
上述案例中,直接设置
setRowStretch
效果不明显,因为每个按钮的⾼度是固定的.需要把按钮的垂直⽅向的sizePolicy
属性设置为QSizePolicy::Expanding
尽可能填充满布局管理器,才能看到效果,如下:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QGridLayout* glayout = new QGridLayout();//创建网格布局,视为2行3列
this->setLayout(glayout);
QPushButton* btn1 = new QPushButton("按钮1");
QPushButton* btn2 = new QPushButton("按钮2");
QPushButton* btn3 = new QPushButton("按钮3");
QPushButton* btn4 = new QPushButton("按钮4");
QPushButton* btn5 = new QPushButton("按钮5");
QPushButton* btn6 = new QPushButton("按钮6");
//设置每个按钮的SizePolicy为 填充
btn1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
btn2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
btn3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
btn4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
btn5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
btn6->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
glayout->addWidget(btn1, 0, 0);
glayout->addWidget(btn2, 0, 1);
glayout->addWidget(btn3, 0, 2);
glayout->addWidget(btn4, 1, 0);
glayout->addWidget(btn5, 1, 1);
glayout->addWidget(btn6, 1, 2);
//设置列的拉伸系数
glayout->setColumnStretch(0,1);
glayout->setColumnStretch(1,2);
glayout->setColumnStretch(2,1);
//设置行的拉伸系数
glayout->setRowStretch(0, 1);
glayout->setRowStretch(1, 3);
}
表单布局
QFormLayout
是表单布局管理器,网格布局的一种特殊情况。这种表单布局多用于让用户填写信息的场景,一般只有两列,左侧列为提示,右侧列为输⼊框。通过addRow(QWidget *label, QWidget *field)
方法可以向表单布局中添加行。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QFormLayout* flayout = new QFormLayout();
this->setLayout(flayout);
QLabel* label_name = new QLabel("姓名");
QLabel* label_phone = new QLabel("电话");
QLabel* label_addr = new QLabel("地址");
QLineEdit* lineEdit_name = new QLineEdit();
QLineEdit* lineEdit_phone = new QLineEdit();
QLineEdit* lineEdit_addr = new QLineEdit();
flayout->addRow(label_name, lineEdit_name);
flayout->addRow(label_phone, lineEdit_phone);
flayout->addRow(label_addr, lineEdit_addr);
QPushButton* btn = new QPushButton("提交");
flayout->addRow(nullptr, btn);
}