Qt --- 常用控件

news2024/11/19 2:47:07

目录

1. 前言

2. QWidget核心属性

2.1. enabled(控件是否可用)

2.2. geometry(尺寸)

2.2.1. windowframe的影响

2.3. windowTitle(窗口标题)

2.4. windowIcon(窗口图标)

2.5. 使用qrc文件资源管理

2.6. windowOpacity(半透明效果)

2.7. cursor(设置鼠标光标)

2.8. font(字体)

2.9. toolTip(鼠标悬停说明)

2.10. focusPolicy(设置控件获取焦点的策略)

2.11. styleSheet(通过CSS设置widget的样式)

3. 常用控件

3.1. 按钮类控件

3.1.1. PushButton(普通按钮)

3.1.1.1. 示例1:带有图标的按钮

3.1.1.2. 示例2:带有快捷键的按钮

3.1.2. RadioButton(单选按钮)

3.1.2.1. 代码示例1:选择技术

3.1.2.2. 代码示例2:click,press,release,toggled的区别

3.1.2.3. 代码示例3:单选框分组

3.1.3. CheckBox(复选按钮)

3.1.3.1. 代码示例:获取复选按钮的取值

3.2. 显示类控件

3.2.1. Label(显示文本和图片)

3.2.1.1. 代码示例1:显示不同格式的文本

3.2.1.2. 代码示例2:显示图片

3.2.1.3. 代码示例3:文本对齐,自动换行,缩进,边距

3.2.1.4. 代码示例4:设置伙伴

3.2.2. LCDNumber(专门用来显示数字)

3.2.2.1. 代码示例1:倒计时

3.2.3. ProgressBar(进度条)

3.2.3.1. 代码示例1:设置进度条按时间增长

3.2.4. CallendarWidget(日历)

3.2.4.1. 代码示例1:获取选中的日期

3.3. 输入类控件

3.3.1. LineEdit(单行输入)

3.3.1.1. 代码示例1:录入个人信息

3.3.1.2. 代码示例2:使用正则表达式验证输入框的数据

3.3.1.3. 代码示例3:切换显示密码

3.3.2. TextEdit(多行输入)

3.3.2.1. 代码示例1:获取多行输入框的内容

3.3.3. ComboBox(下拉框)

3.3.3.1. 代码示例1:使用下拉框模拟点餐

3.3.3.2. 代码示例2:从文件中加载下拉框的选项

3.3.4. SpinBox(微调框)

3.3.4.1. 代码示例1:调正购物车中的份数

3.3.5. DateEdit&TimeEdit&DateTimeEdit(日期&时间&时间日期的微调框)

3.3.5.1. 代码示例1:实现日期计算器

3.3.6. Dial(旋钮)

3.3.6.1. 代码示例1:调整窗口透明度

3.3.7. Slider(滑动条)

3.3.7.1. 代码示例1:

3.4. 多元素控件

3.4.1. ListWidget(纵向的列表)

3.4.1.1. 代码示例1:使用ListWidget

3.4.2. TableWidget(表格控件)

3.4.2.1. 代码示例1:使用QTableWidget

3.4.3. TreeWidget(树形控件)

3.4.3.1. 代码示例1:QTreeWidget

3.5. 容器类控件

3.5.1. GroupBox(分组框)

3.5.1.1. 代码示例1:给麦当劳案例加上分组框

3.5.2. TabWidget(带有标签页的控件)

3.5.2.1. 代码示例1:使用标签页管理多组控件

3.6. 布局管理器

3.6.1. QVBoxLayout(垂直布局)

3.6.1.1. 代码示例1:使用QVBoxLayout管理多个控件

3.6.2. QHBoxLayout(水平布局)

3.6.2.1. 代码示例1:使用QHBoxLayout管理控件

3.6.2.2. 代码示例2:嵌套布局

3.6.3. QGridLayout(网格布局)

3.6.3.1. 代码示例1:使用QGridLayout管理元素

3.6.4. 表单布局

3.6.4.1. 代码示例1:使用QFormLayout创建表单

3.6.5. Spacer(添加一段空白)

3.6.5.1. 代码示例1:创建一组左右排列的按钮


1. 前言

Widget(控件)是Qt中的核心概念,控件是构成一个图形化界面的基本要素。

比如说QtCreator创建项目之后的窗口,用到的就有按钮,树形视图,列表视图,单行输入框,多行输入框等等,这些都是控件。

Qt作为⼀个成熟的GUI开发框架,内置了⼤量的常⽤控件.这⼀点在QtDesigner中就可以看到端倪.并且Qt也提供了"⾃定义控件"的能⼒,可以让程序猿在现有控件不能满⾜需求的时候,对现有控件做出扩展,或者⼿搓出新的控件.

2. QWidget核心属性

在Qt中,使用QWidget类表示"控件",像按钮,视图,输入框,滚动条等具体的控件类,都是继承自QWidget。可以说是,QWidget中就包含了Qt整个控件体系中通用的部分。

在QtDesigner中,随便拖一个控件过来,选中该控件,即可在右下方看到QWidget中的属性。

这些属性既可以通过QtDesigner直接修改,也可以通过代码的方式修改。

2.1. enabled(控件是否可用)

描述了一个控件是否处于可用的状态。

API

说明

isEnabled()

获取到控件的可⽤状态.

setEnabled

设置控件是否可使⽤.true表⽰可⽤,false表⽰禁⽤

所谓的禁用指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。

如果一个widget被禁用,则该widget的子元素也被禁用

代码示例:使用代码创建一个禁用状态的按钮

#include"widget.h"
#include"ui_widget.h"

#include<QPushButton>
#include<QDebug>

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
QPushButton*btn=newQPushButton(this);
btn->setText("button");
btn->setEnabled(false);//此时按钮就处于禁用状态。
}

Widget::~Widget()
{
deleteui;
}

运行程序,可以看到按钮是灰色的,不能被点击。


代码示例:通过按钮2切换按钮1的禁用状态

  1. 使用QtDesigner拖两个按钮到Widget中

两个按钮的objectName分别为pushButton和pushButton_2
2.生成两个按钮的slot函数

  1. 使用isEnabled获取当前按钮的状态
  2. 使用setEnabled修改按钮的可用状态,此处是直接针对原来的可用状态进行取反后设置。
#include"widget.h"
#include"ui_widget.h"

#include<QDebug>
#include<QPushButton>

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
}

Widget::~Widget()
{
deleteui;
}


voidWidget::on_pushButton_clicked()
{
qDebug()<<"点击按钮";
}

voidWidget::on_pushButton_2_clicked()
{
boolenable=this->ui->pushButton->isEnabled();
if(enable)
{
this->ui->pushButton->setEnabled(false);
}
else
{
this->ui->pushButton->setEnabled(true);
}
}

运⾏程序,可以看到,初始情况下,上⾯的按钮是可⽤状态.
点击下⽅按钮,即可使上⽅按钮被禁⽤;再次点击下⽅按钮,上⽅按钮就会解除禁⽤.(禁⽤状态的按钮为灰⾊,且不可点击).

2.2. geometry(尺寸)

位置和尺寸,其实是四个属性的统称

  1. x横坐标
  2. y纵坐标
  3. width宽度
  4. height高度

但是实际开发中,我们并不会直接使⽤这⼏个属性,⽽是通过⼀系列封装的⽅法来获取/修改.
对于Qt的坐标系,不要忘记是⼀个"左⼿坐标系".其中坐标系的原点是当前元素的⽗元素的左上⻆

API

说明

geometry()

获取到控件的位置和尺⼨.返回结果是⼀个QRect,包含了x,y,width,height.其
中x,y是左上⻆的坐标.

setGeometry(QRect)
setGeometry(intx,inty,
intwidth,intheight)

设置控件的位置和尺⼨.可以直接设置⼀个QRect,也可以分四个属性单独设置.


代码示例:控制按钮的位置

在界⾯中拖五个按钮.五个按钮的objectName分别为pushButton_target,pushButton_up,
pushButton_down,pushButton_left,pushButton_right五个按钮的初始位置和⼤⼩都随意.

在widget.cpp中编写四个按钮的slot函数

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
}

test::~test()
{
deleteui;
}

voidtest::on_pushButton_up_clicked()
{
QRectrect=ui->pushButton_target->geometry();
qDebug()<<rect;
rect.setY(rect.y()-5);
ui->pushButton_target->setGeometry(rect);
}

voidtest::on_pushButton_left_clicked()
{
QRectrect=ui->pushButton_target->geometry();
qDebug()<<rect;
rect.setX(rect.x()-5);
ui->pushButton_target->setGeometry(rect);
}

voidtest::on_pushButton_down_clicked()
{
QRectrect=ui->pushButton_target->geometry();
qDebug()<<rect;
rect.setY(rect.y()+5);
ui->pushButton_target->setGeometry(rect);
}

voidtest::on_pushButton_right_clicked()
{
QRectrect=ui->pushButton_target->geometry();
qDebug()<<rect;
rect.setX(rect.x()+5);
ui->pushButton_target->setGeometry(rect);
}

运⾏程序,可以看到,按下下⽅的四个按钮,就会控制target的左上⻆的位置.对应的按钮整个尺⼨也会发⽣改变.
上述代码中我们是直接设置的QRect中的x,y.实际上QRect内部是存储了左上和右下两个点的坐标,再通过这两个点的坐标差值计算⻓宽.单纯修改左上坐标就会引起整个矩形的⻓宽发⽣改变.

2.2.1. windowframe的影响

如果widget作为⼀个窗⼝(带有标题栏,最⼩化,最⼤化,关闭按钮),那么在计算尺⼨和坐标的
时候就有两种算法.包含windowframe和不包含windowframe.
其中x(),y(),frameGeometry(),pos(),move()都是按照包含windowframe的⽅式来计算
的.
其中geometry(),width(),height(),rect(),size()则是按照不包含windowframe的⽅式来计
算的.
当然,如果⼀个不是作为窗⼝的widget,上述两类⽅式得到的结果是⼀致的.


相关API

API

说明

x()

获取横坐标
计算时包含windowframe

y()

获取纵坐标
计算时包含windowframe

pos()

返回QPoint对象,⾥⾯包含x(),y(),setX(),setY()等⽅法.
计算时包含windowframe

frameSize()

返回QSize对象,⾥⾯包含width(),height(),setWidth(),setHeight()等⽅法.
计算时包含windowframe

frameGeometry()

返回QRect对象.QRect相当于QPoint和QSize的结合体.可以获取x,y,
width,size.
计算时包含windowframe对象.

width()

获取宽度
计算时不包含windowframe

height()

获取⾼度

计算时不包含windowframe

size()

返回QSize对象,⾥⾯包含width(),height(),setWidth(),setHeight()等⽅法.
计算时不包含windowframe

rect()

返回QRect对象.QRect相当于QPoint和QSize的结合体.可以获取并设置x,
y,width,size.
计算时不包含windowframe对象.

geometry()

返回QRect对象.QRect相当于QPoint和QSize的结合体.可以获取x,y,
width,size.
计算时不包含windowframe对象.

setGeometry()

直接设置窗⼝的位置和尺⼨.可以设置x,y,width,height,或者QRect对象.
计算时不包含windowframe对象

代码示例:将geometry和frameGeometry打印出来感受一下

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);

QRectrect1=this->geometry();
QRectrect2=this->frameGeometry();
qDebug()<<rect1;
qDebug()<<rect2;
}

test::~test()
{
deleteui;
}


voidtest::on_pushButton_clicked()
{
qDebug()<<"1";
QRectrect1=this->geometry();
QRectrect2=this->frameGeometry();
qDebug()<<rect1;
qDebug()<<rect2;
}

在初始的时候是一样的,点击按钮之和,发生了变化。

🏝注意!
在构造⽅法中,Widget刚刚创建出来,还没有加⼊到对象树中.此时也就不具备Window
frame.
在按钮的slot函数中,由于⽤⼾点击的时候,对象树已经构造好了,此时Widget已经具备了
Windowframe,因此在位置和尺⼨上均出现了差异.
如果把上述代码修改成打印pushButton的geometry和frameGeometry,结果就是完全相
同的.因为pushButton并⾮是⼀个窗⼝

2.3. windowTitle(窗口标题)

API

说明

windowTitle()

获取到控件的窗⼝标题.

setWindowTitle(const
QString&title)

设置控件的窗⼝标题.

🍰注意!上述设置操作针对不同的widget可能会有不同的⾏为.
如果是顶层widget(独⽴窗⼝),这个操作才会有效.
如果是⼦widget,这个操作⽆任何效果.

代码示例:设置窗口标题

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
this->setWindowTitle("这是一个窗口标题");
}

test::~test()
{
deleteui;
}


test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
this->setWindowTitle("这是一个窗口标题");

QPushButton*btn=newQPushButton(this);
btn->setText("按钮");
btn->setWindowTitle("这是一个按钮窗口");
}

windowTitle属性,只能针对顶层的widget才能生效。当前不应该给按钮设置windowTitle,但是实际设置了之和,没有任何效果,也没有报错。还是希望当代码写的不太科学的时候,能给出一些报错提示。

2.4. windowIcon(窗口图标)

API

说明

windowIcon()

获取到控件的窗⼝图标.返回QIcon对象.

setWindowIcon(const
QIcon&icon)

设置控件的窗⼝图标.

🎹同windowTitle,上述操作仅针对顶层widget有效.

代码示例:将上面的图片设置为窗口的图标

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>
#include<QIcon>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
QIconicon("C:/Users/Lenovo/Pictures/1664844094688.png.jpg");
this->setWindowIcon(icon);
}

test::~test()
{
deleteui;
}


如果说上面的代码路径出错或者图片被删了,就会导入图片加载不出来。

对此Qt引入了qrc机制,这个机制就是从根本上解决上述两个问题的。确保图片所在的路径在目标用户机器上存在,确保图片不会被搞没了。给Qt项目引入一个额外的xml文件(后缀名使用.qrc表示)在这个xml中要把使用的图片资源给导入进来,并且在xml中进行记录。Qt在编译项目的时候,就会根据qrc中描述的图片信息,找到图片内容,并且提取出图片的二进制数据,把这些二进制数据转成C++代码,最终编译到exe里。

当然这个机制也是有缺点的,无法导入太大的资源文件,比如搞几个gb这种视频文件,qrc就无能为力了。

2.5. 使用qrc文件资源管理

代码示例:通过qtc管理图片作为图标

创建一个QtResourceFile(qrc文件),文件名随意起(不能有中文),

添加之后会得到一个这样的页面

在qrc编辑器中,添加前缀(点击AddPrefix)

这里我们把前缀设置为/即可。

所谓的前缀,可以理解成"⽬录".这个前缀决定了后续我们如何在代码中访问资源.
 


在资源编辑器中,点击addDiles添加资源文件,此处我们把上面的图片给添加进去。

在添加图片之前,要确保导入的图片必须在resource.qrc文件的同级目录,或者同级目录的子目录里面。

添加完毕后,可以在资源编辑器中看到添加好的⽂件

在代码中使用这张图片。

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>
#include<QIcon>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
QIconicon(":/1664844094688.png.jpg");
this->setWindowIcon(icon);
}

test::~test()
{
deleteui;
}

使用:作为开头,表示从qrc中读取资源,

/是上面配置的前缀

1664844094688.png.jpg是资源的名称


接下来,我们可以进⼊到项⽬的构建⽬录,可以看到,⽬录中多了⼀个qrc_resource.cpp⽂件.直
接打开这个⽂件,可以看到类似如下代码:

上述代码其实就是通过unsignedchar数组,把rose.jpg中的每个字节都记录下来.这些代码会被编译到exe中.后续⽆论exe被复制到哪个⽬录下,都确保能够访问到该图⽚资源.

2.6. windowOpacity(半透明效果)

API

说明

windowOpacity()

获取到控件的不透明数值.返回float,取值为0.0->1.0其中0.0表⽰全透明,1.0表⽰完全不透明.

setWindowOpacity(floatn)

设置控件的不透明数值.

代码示例:调整按钮透明度

  1. 在界面上拖放两个按钮,分别用来表示按钮,增加透明度,减少透明度
    objectName为pushButton_add,pushButton_sub。

  1. 编写cpp函数,点击sub会减少透明度,点击add会增加透明度。
#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>
#include<QIcon>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
}


test::~test()
{
deleteui;
}


voidtest::on_pushButton_add_clicked()
{
floatopacity=this->windowOpacity();
if(opacity>=1.0)return;
qDebug()<<opacity;
opacity+=0.1;
this->setWindowOpacity(opacity);
}

voidtest::on_pushButton_sub_clicked()
{
floatopacity=this->windowOpacity();
if(opacity<=0.0)return;
qDebug()<<opacity;
opacity-=0.1;
this->setWindowOpacity(opacity);
}

注意,C++中float类型遵守IEEE754标准,因此在进⾏运算的时候会有⼀定的精度误差.因此1-0.1的数值并⾮是0.9.
 


 

2.7. cursor(设置鼠标光标)

API

说明

cursor()

获取到当前widget的cursor属性,返回QCursor对象.
当⿏标悬停在该widget上时,就会显⽰出对应的形状.

setCursor(constQCursor&cursor)

设置该widget光标的形状.仅在⿏标停留在该widget上时⽣效.

QGuiApplication::setOverrideCursor(constQCursor&cursor)

设置全局光标的形状.对整个程序中的所有widget都会⽣效.覆盖上⾯的setCursor设置的内容.

代码示例:设置按钮的光标

在Designer中拖出来一个按钮,然后在cpp文件中设置点击按钮之后的光标。

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>
#include<QIcon>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
}


test::~test()
{
deleteui;
}


voidtest::on_pushButton_clicked()
{
QCursorcursor(Qt::WaitCursor);
ui->pushButton->setCursor(cursor);
}

emm,截图失败,请自行演示。


系统内置的光标形状如下:

Ctrl+左键点击Qt::WaitCursor跳转到源码即可看到。

enumCursorShape{
ArrowCursor,
UpArrowCursor,
CrossCursor,
WaitCursor,
IBeamCursor,
SizeVerCursor,
SizeHorCursor,
SizeBDiagCursor,
SizeFDiagCursor,
SizeAllCursor,
BlankCursor,
SplitVCursor,
SplitHCursor,
PointingHandCursor,
ForbiddenCursor,
WhatsThisCursor,
BusyCursor,
OpenHandCursor,
ClosedHandCursor,
DragCopyCursor,
DragMoveCursor,
DragLinkCursor,
LastCursor=DragLinkCursor,
BitmapCursor=24,
CustomCursor=25
};

当然也可以使用自定义的光标。

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>
#include<QIcon>
#include<QPixmap>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
//创建一个位图对象,加载自定义光标图片
QPixmappixmap(":/1664844094688.png.jpg");
//缩放图片为64*64的尺寸
pixmap=pixmap.scaled(64,64);
//创建QCursor对象,并指定热点为(2,2)坐标位置
//所谓热点就是鼠标点击时生效的位置
QCursorcursor(pixmap,2,2);
//设置光标
this->setCursor(cursor);
}


test::~test()
{
deleteui;
}

截图失败,在载入qrc资源后自行测试。

2.8. font(字体)

API

说明

font()

获取当前widget的字体信息.返回QFont对象.

setFont(constQFont&font)

设置当前widget的字体信息.

关于QFont

属性

说明

family

字体家族.⽐如"楷体","宋体","微软雅⿊"等.

pointSize

字体⼤⼩

weight

字体粗细.以数值⽅式表⽰粗细程度取值范围为[0,99],数值越⼤,越
粗.

bold

是否加粗.设置为true,相当于weight为75.设置为false相当于
weight为50.

italic

是否倾斜

underline

是否带有下划线

strikeOut

是否带有删除线

代码示例:使用代码设置字体属性

在界⾯上创建⼀个label


如果你想使用Designer来设置字体属性,可以在ui中的右下角找到font属性,修改font中的属性,就可以完成对自己的改变了。


在cpp文件中对label进行修改

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>
#include<QIcon>
#include<QPixmap>
#include<QFont>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);
//设置label的文本内容
ui->label->setText("这是一段文本");
//创建字体对象
QFontfont;
//设置字体家族
font.setFamily("宋体");
//设置字体大小
font.setPointSize(20);
//设置字体加粗
font.setBold(true);
//设置字体倾斜
font.setItalic(true);
//设置字体下划线
font.setUnderline(true);
//设置字体删除线
font.setStrikeOut(true);
//设置自己对象到label上
ui->label->setFont(font);
}


test::~test()
{
deleteui;
}

2.9. toolTip(鼠标悬停说明)

API

说明

setToolTip

设置toolTip.
⿏标悬停在该widget上时会有提⽰说明.

setToolTipDuring

设置toolTip提⽰的时间.单位ms.
时间到后toolTip⾃动消失.

toolTip只是给⽤⼾看的.在代码中⼀般不需要获取到toolTip.
代码⽰例:设置按钮的toolTip
1)在界⾯上拖放两个按钮.objectName设置为pushButton_yes和pushButton_no
 


2)编写test.cpp

#include"test.h"
#include"ui_test.h"
#include<QPushButton>
#include<QDebug>
#include<QIcon>
#include<QPixmap>
#include<QFont>

test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);

ui->pushButton_yes->setToolTip("这是一个yes");
ui->pushButton_yes->setToolTipDuration(3000);

ui->pushButton_no->setToolTip("这是一个no");
ui->pushButton_no->setToolTipDuration(3000);
}

test::~test()
{
deleteui;
}

系统截图⽆法截取到⿏标光标

2.10. focusPolicy(设置控件获取焦点的策略)

设置控件获取到焦点的策略.⽐如某个控件能否⽤⿏标选中或者能否通过tab键选中.
所谓"焦点",指的就是能选中这个元素.接下来的操作(⽐如键盘操作),就都是针对该焦点元素进⾏的了.这个对于输⼊框,单选框,复选框等控件⾮常有⽤的.

API

说明

focusPolicy()

获取该widget的focusPolicy,返回Qt::FocusPolicy

setFocusPolicy(Qt::FocusPolicypolicy)

设置widget的focusPolicy.

Qt::FocusPolicy是⼀个枚举类型.取值如下
•Qt::NoFocus:控件不会接收键盘焦点
•Qt::TabFocus:控件可以通过Tab键接收焦点
•Qt::ClickFocus:控件在⿏标点击时接收焦点
•Qt::StrongFocus:控件可以通过Tab键和⿏标点击接收焦点(默认值)
•Qt::WheelFocus:类似于Qt::StrongFocus,同时控件也通过⿏标滚轮获取到焦点(新增
的选项,⼀般很少使⽤).

代码⽰例:理解不同的focusPolicy
1)在界⾯上创建四个单⾏输⼊框(LineEdit)

2)修改四个输⼊框的focusPolicy属性为Qt::StrongFocus(默认取值,⼀般不⽤额外修改)

此时运⾏程序,可以看到,使⽤⿏标单击/tab,就可以移动光标所在输⼊框.从⽽接下来的输⼊就是针对这个获取焦点的输⼊框展开的了.
3)修改第⼆个输⼊框的focusPolicy为Qt::NoFocus,则第⼆个输⼊框不会被tab/⿏标左键选中.

此时这个输⼊框也就⽆法输⼊内容了.
4)修改第⼆个输⼊框focusPolicy为Qt::TabFocus,则只能通过tab选中,⽆法通过⿏标选
中.

5)修改第⼆个输⼊框focusPolicy为Qt::ClickFocus,则只能通过tab选中,⽆法通过⿏标
选中.

2.11. styleSheet(通过CSS设置widget的样式)

🎨CSS(CascadingStyleSheets层叠样式表)本⾝属于⽹⻚前端技术.主要就是⽤来描述界⾯的样式.所谓"样式",包括不限于⼤⼩,位置,颜⾊,间距,字体,背景,边框等.
我们平时看到的丰富多彩的⽹⻚,就都会⽤到⼤量的CSS.Qt虽然是做GUI开发,但实际上和⽹⻚前端有很多异曲同⼯之处.因此Qt也引⼊了对于CSS的⽀持.

CSS中可以设置的样式属性⾮常多.基于这些属性Qt只能⽀持其中⼀部分,称为QSS(QtStyleSheet)
此处只是进⾏⼀个简单的演⽰.
代码⽰例:设置⽂本样式
1)在界⾯上创建label

2)编辑右侧的styleSheet属性,设置样式

此处的语法格式同CSS,使⽤键值对的⽅式设置样式.其中键和值之间使⽤:分割.键值对之间使⽤;分割.另外,QtDesigner只能对样式的基本格式进⾏校验,不能检测出哪些样式不被Qt⽀持.⽐如textalign:center这样的⽂本居中操作,就⽆法⽀持.
编辑完成样式之后,可以看到在QtDesigner中能够实时预览出效果.

3)运⾏程序,可以看到实际效果和预览效果基本⼀致


3. 常用控件

Qt中提供的各种控件都继承与QWidget,所以上面说的QWidget中设计到的各种函数,对于下面的各种控件都是有效的。

在学C/C++的时候,应该是了解过抽象类的,抽象类包含了纯虚函数,无法创建出实例对象,要创建出实例对象,就得创建子类,重写虚函数。

3.1. 按钮类控件

3.1.1. PushButton(普通按钮)

使用QPushButton表示一个按钮,QPushButton继承于QAbstractButton,这个类是一个抽象类,是其他按钮的父类。

在QtDesigner中也能看到这里的继承关系。

QAbstractButton中,和QPushButton相关性较⼤的属性。

属性

说明

text

按钮中的⽂本

icon

按钮中的图标

iconSize

按钮中图标的尺⼨

shortCut

按钮对应的快捷键

autoRepeat

按钮是否会重复触发.当⿏标左键按住不放时,
如果设为true,则会持续产⽣⿏标点击事件;
如果设为false,则必须释放⿏标,再次按下⿏标时才能产⽣点击事件.
(相当于游戏⼿柄上的"连发"效果)

autoRepeatDelay

重复触发的延时时间.按住按钮多久之后,开始重复触发.

autoRepeatInterval

重复触发的周期.

  1. QAbstractButton作为QWidget的⼦类,当然也继承了QWidget的属性.上⾯
    介绍的QWidget⾥的各种属性⽤法,对于QAbstractButton同样适⽤.因此表格仅
    列出QAbstractButton独有的属性.
  2. Qt的api设计⻛格是⾮常清晰的.此处列出的属性都是可以获取和设置的.例如,使
    ⽤text()获取按钮⽂本;使⽤setText()设置⽂本.

事实上,QPushButton的核⼼功能都是QAbstractButton提供的.⾃⾝提供的属性都⽐较简单.其中default和audoDefault影响的是按下enter时⾃动点击哪个按钮的⾏为;flat把按钮设置为扁平的样式.这⾥我们暂时都不做过多关注.

3.1.1.1. 示例1:带有图标的按钮
  1. 创建qrc文件,并导入图片
  2. 在界面上创建一个按钮

  1. 修改widget.cpp,给按钮设置图标
test::test(QWidget*parent)
:QWidget(parent)
,ui(newUi::test)
{
ui->setupUi(this);

QIconicon(":/1664844094688.png.jpg");
ui->pushButton->setIcon(icon);

ui->pushButton->setIconSize(QSize(50,50));
}
  1. 执行程序,观察效果

3.1.1.2. 示例2:带有快捷键的按钮
  1. 在界面中拖五个按钮
    objectName分别为:pushButton_target/left/right/up/low

  1. 创建qrc,并导入五个图片

  2. 修改widget.cpp,设置图标资源和快捷键

使用setShortcut给按钮设置快捷键,参数是一个QKeySequence对象,表示一个按键序列,支持组合键。

QKeySequence的构造函数参数,可以直接使用ctrl+c这样的案件名字符串表示,也可以使用预定义好的常量如(Qt::CTRL+Qt::Key_C)表示。

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
ui->pushButton_target->setIcon(QIcon(":/1664844094688.png.jpg"));
ui->pushButton_target->setIconSize(QSize(80,80));

ui->pushButton_up->setIcon(QIcon(":/up.png"));
ui->pushButton_up->setIconSize(QSize(80,80));

ui->pushButton_low->setIcon(QIcon(":/down.png"));
ui->pushButton_low->setIconSize(QSize(80,80));

ui->pushButton_left->setIcon(QIcon(":/left.png"));
ui->pushButton_left->setIconSize(QSize(80,80));

ui->pushButton_right->setIcon(QIcon(":/right.png"));
ui->pushButton_right->setIconSize(QSize(80,80));

//ui->pushButton_up->setShortcut(QKeySequence("w"));
//ui->pushButton_low->setShortcut(QKeySequence("s"));
//ui->pushButton_left->setShortcut(QKeySequence("a"));
//ui->pushButton_right->setShortcut(QKeySequence("d"));

ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_W));
ui->pushButton_low->setShortcut(QKeySequence(Qt::Key_S));
ui->pushButton_left->setShortcut(QKeySequence(Qt::Key_A));
ui->pushButton_right->setShortcut(QKeySequence(Qt::Key_D));
}
  1. 修改widget.cpp,设置四个方向键的slot函数
voidWidget::on_pushButton_left_clicked()
{
QRectrect=ui->pushButton_target->geometry();
ui->pushButton_target->setGeometry(rect.x()-5,rect.y(),rect.width(),rect.height());
}

voidWidget::on_pushButton_up_clicked()
{
QRectrect=ui->pushButton_target->geometry();
ui->pushButton_target->setGeometry(rect.x(),rect.y()-5,rect.width(),rect.height());
}
voidWidget::on_pushButton_low_clicked()
{
QRectrect=ui->pushButton_target->geometry();
ui->pushButton_target->setGeometry(rect.x(),rect.y()+5,rect.width(),rect.height());
}
voidWidget::on_pushButton_right_clicked()
{
QRectrect=ui->pushButton_target->geometry();
ui->pushButton_target->setGeometry(rect.x()+5,rect.y(),rect.width(),rect.height());
}
  1. 运行程序,此时点击按钮,或使用wasd就可以让图片移动了。
  2. 按钮的重复触发

上面的例子中,按快捷键是可以重复触发的,但是鼠标点击不能。修改widget函数,在构造函数中开启重复触发。

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
ui->pushButton_target->setIcon(QIcon(":/1664844094688.png.jpg"));
ui->pushButton_target->setIconSize(QSize(80,80));

ui->pushButton_up->setIcon(QIcon(":/up.png"));
ui->pushButton_up->setIconSize(QSize(80,80));

ui->pushButton_low->setIcon(QIcon(":/down.png"));
ui->pushButton_low->setIconSize(QSize(80,80));

ui->pushButton_left->setIcon(QIcon(":/left.png"));
ui->pushButton_left->setIconSize(QSize(80,80));

ui->pushButton_right->setIcon(QIcon(":/right.png"));
ui->pushButton_right->setIconSize(QSize(80,80));

//ui->pushButton_up->setShortcut(QKeySequence("w"));
//ui->pushButton_low->setShortcut(QKeySequence("s"));
//ui->pushButton_left->setShortcut(QKeySequence("a"));
//ui->pushButton_right->setShortcut(QKeySequence("d"));

ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_W));
ui->pushButton_low->setShortcut(QKeySequence(Qt::Key_S));
ui->pushButton_left->setShortcut(QKeySequence(Qt::Key_A));
ui->pushButton_right->setShortcut(QKeySequence(Qt::Key_D));

ui->pushButton_up->setAutoRepeat(true);
ui->pushButton_left->setAutoRepeat(true);
ui->pushButton_right->setAutoRepeat(true);
ui->pushButton_low->setAutoRepeat(true);
}

3.1.2. RadioButton(单选按钮)

QRadioButton是单选按钮,可以让我们在多个选项中选择一个。

作为QAbstractButton和QWidget的子类,上面介绍的函数,对于QRadioButton一样使用。

QAbstractButton中和QRadioButton关系较大的属性

属性

说明

checkable

是否能选中

checked

是否已经被选中.checkable是checked的前提条件.

autoExclusive

是否排他.
选中⼀个按钮之后是否会取消其他按钮的选中.
对于QRadioButton来说默认就是排他的.

3.1.2.1. 代码示例1:选择技术
  1. 在界面上创建一个label,和n个单选按钮

三个单选按钮的objectName分别为radioButton_java/python/c++/php/go

  1. 修改widget.cpp,编辑三个QRadioButton的slot函数.
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
ui->radioButton_c->setChecked(true);//默认选项
//如果将true改为false
ui->label->setText("技术;c++");
}

voidWidget::on_radioButton_java_clicked()
{
ui->label->setText("技术:java");
}

voidWidget::on_radioButton_python_clicked()
{
ui->label->setText("技术:python");
}

voidWidget::on_radioButton_c_clicked()
{
ui->label->setText("技术:c++");
}

voidWidget::on_radioButton_other_clicked()
{
ui->label->setText("技术:other");
}

使用setEnabled可以彻底禁用按钮。

3.1.2.2. 代码示例2:click,press,release,toggled的区别
  1. clicked表⽰⼀次"点击"
  2. pressed表⽰⿏标"按下"
  3. released表⽰⿏标"释放"
  4. toggled表⽰按钮状态切换

  1. 在界面上创建四个单选按钮,objectName分别为radioButton_1/2/3/4

  1. 给1创建clicked槽函数,给2创建pressed槽函数,给3创建released槽函数,给4创建toggled槽函数
voidWidget::on_radioButton_1_clicked(boolchecked)
{
qDebug()<<"clicked"<<checked;
}

voidWidget::on_radioButton_2_pressed()
{
qDebug()<<"pressed";
}
voidWidget::on_radioButton_3_released()
{
qDebug()<<"released";
}
voidWidget::on_radioButton_4_toggled(booltoggled)
{
qDebug()<<"toggled"<<toggled;
}
  1. 运行程序可以看到

clicked是一次鼠标按下+释放触发的

pressed是鼠标按下触发的

released是鼠标释放触发的

toggled是checked属性改变时触发的

3.1.2.3. 代码示例3:单选框分组
  1. 在界面上创建6个单选框,用来模拟麦当劳点餐界面,objectName分别为radioButton到radioButton_6

此时直接运行程序,可以看到这6个QadioButton之间都是排他的。

  1. 引入QButtonGroup进行分组
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

QButtonGroup*group1=newQButtonGroup();
QButtonGroup*group2=newQButtonGroup();
QButtonGroup*group3=newQButtonGroup();

group1->addButton(ui->radioButton_1);
group1->addButton(ui->radioButton_2);

group2->addButton(ui->radioButton_3);
group2->addButton(ui->radioButton_4);

group3->addButton(ui->radioButton_5);
group3->addButton(ui->radioButton_6);

}

再次执行程序,就可以看到组与组之间能够完成排他了。

3.1.3. CheckBox(复选按钮)

QCheckBox表示复选按钮,可以允许选中多个。和QCheckBox下才能过关的属性是checkable和checked,都是继承于QAstractButton,QCheckBox独有的属性tristate用来实现"三态复选框"

3.1.3.1. 代码示例:获取复选按钮的取值
  1. 在界面上创建三个复选按钮,和一个普通按钮,objectName分别为checkBox_eat/sleep/play和pushButton

  1. 给pushButton添加slot函数
voidWidget::on_pushButton_clicked()
{
QStringret="今日安排";
if(ui->checkBox_play->isChecked())
{
ret+=ui->checkBox_play->text();
}
if(ui->checkBox_eat->isChecked())
{
ret+=ui->checkBox_eat->text();
}
if(ui->checkBox_sleep->isChecked())
{
ret+=ui->checkBox_sleep->text();
}
ui->label->setText(ret);
}
  1. 运行程序

3.2. 显示类控件

3.2.1. Label(显示文本和图片)

QLabel可以用来显示文本和图片。

属性

说明

text

QLabel中的⽂本

textFormat

⽂本的格式.
Qt::PlainText纯⽂本
Qt::RichText富⽂本(⽀持html标签)
Qt::MarkdownTextmarkdown格式
Qt::AutoText根据⽂本内容⾃动决定⽂本格式.

pixmap

QLabel内部包含的图⽚.

scaledContents

设为true表⽰内容⾃动拉伸填充QLabel
设为false则不会⾃动拉伸

alignment

对⻬⽅式.
可以设置⽔平和垂直⽅向如何对⻬.

wordWrap

设为true内部的⽂本会⾃动换⾏.
设为false则内部⽂本不会⾃动换⾏.

indent

设置⽂本缩进.⽔平和垂直⽅向都⽣效.

margin

内部⽂本和边框之间的边距.
不同于于indent,但是是上下左右四个⽅向都同时有效.
⽽indent最多只是两个⽅向有效(具体哪两个⽅向有效取决于alignment)

openExternalLinks

是否允许打开⼀个外部的链接.
(当QLabel⽂本内容包含url的时候涉及到)

buddy

给QLabel关联⼀个"伙伴",这样点击QLabel时就能激活对应的伙伴.
例如伙伴如果是⼀个QCheckBox,那么该QCheckBox就会被选中.

3.2.1.1. 代码示例1:显示不同格式的文本
  1. 在界面上创建三个QLabel,尺寸放大一些,objectName分别为label_1/2/3

  1. 修改widget.cpp,设置三个label属性
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
ui->label_1->setTextFormat(Qt::PlainText);
ui->label_1->setText("这是纯文本");

ui->label_2->setTextFormat(Qt::RichText);
ui->label_2->setText("<b>这是一段富文本<b/>");

ui->label_3->setTextFormat(Qt::MarkdownText);
ui->label_3->setText("#这是一段Markdown文本");
}
  1. 运行程序

3.2.1.2. 代码示例2:显示图片
  1. 在界面上创建一个QLabel并创建qrc文件,把要显示的文件导入到qrc中
  2. 修改widget.cpp文件
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
ui->label->setGeometry(0,0,800,600);
QPixmappixmap(":/1664844094688.png.jpg");
ui->label->setPixmap(pixmap);
}
  1. 运行程序

  1. 通过scaledContents把QLabel填充满
ui->label->setScaledContents(true);

  1. 此时拖动窗口大小,图片并不会随着发生变化,可以在Widget中重写resizeEvent函数,解决这个问题
#include<QResizeEvent>
#include<QSize>
voidWidget::resizeEvent(QResizeEvent*event)
{
//可以直接通过this->width()和this->height()设置label新的尺⼨,也可以通过
//event参数拿到新的尺⼨.
//ui->label->setGeometry(0,0,this->width(),this->height());
ui->label->setGeometry(0,0,event->size().width(),event->size().height());
qDebug()<<event->size();
}

此处的resizeEvent函数我们没有⼿动调⽤,但是能在窗⼝⼤⼩变化时被⾃动调⽤.这个过程就是依赖C++中的多态来实现的.Qt框架内部管理着QWidget对象表⽰咱们的窗⼝.在窗⼝⼤⼩发⽣改变时,Qt就会⾃动调⽤resizeEvent函数.但是由于实际上这个表⽰窗⼝的并⾮是QWidget,⽽是QWidget的⼦类,也就是咱们⾃⼰写的Widget.此时虽然是通过⽗类调⽤函数,但是实际上执⾏的是⼦类的函数(也就是我们重写后的resizeEvent).此处属于是多态机制的⼀种经典⽤法.通过上述过程,就可以把⾃定义的代码,插⼊到框架内部执⾏.相当于"注册回调函数".

3.2.1.3. 代码示例3:文本对齐,自动换行,缩进,边距
  1. 创建4个label,objectName分别为label_1/2/3/4,并在QFrame中设置frameShape为Box

QFrame是QLabel的⽗类.其中frameShape属性⽤来设置边框性质.
QFrame::Box:矩形边框
QFrame::Panel:带有可点击区域的⾯板边框
QFrame::WinPanel:Windows⻛格的边框
QFrame::HLine:⽔平线边框
QFrame::VLine:垂直线边框
QFrame::StyledPanel:带有可点击区域的⾯板边框,但样式取决于窗⼝主题

  1. 修改widget.cpp文件
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

ui->label_1->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
ui->label_1->setText("垂直+水平居中的文本");

ui->label_2->setWordWrap(true);
ui->label_2->setText("这是一段会自动换行的文本|这是一段会自动换行的文本|这是一段会自动换行的文本|这是一段会自动换行的文本");

ui->label_3->setIndent(50);
ui->label_3->setText("这是一段会自动缩进的文本");

ui->label_4->setMargin(20);
ui->label_4->setText("这是设置边距的文本");
}
  1. 执行代码

3.2.1.4. 代码示例4:设置伙伴
  1. 创建两个label和两个radioButton,objectName分别为label_1/2,radioButton_1/2

此处把label中的⽂本设置为"快捷键&A"这样的形式.
其中&后⾯跟着的字符,就是快捷键.
可以通过alt+A的⽅式来触发该快捷键.
但是注意,这⾥的快捷键和QPushButton的不同.需要搭配alt和单个字⺟的⽅式才能触发.

  1. 编写widget.cpp
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
//设置radioButton和label的伙伴关系
ui->label_1->setBuddy(ui->radioButton_1);
ui->label_2->setBuddy(ui->radioButton_2);
}
  1. 执行代码

3.2.2. LCDNumber(专门用来显示数字)

QLCDNumber是一个专门用来显示数字的控件。

属性

说明

intValue

QLCDNumber显⽰的数字值(int).

value

QLCDNumber显⽰的数字值(double).
和intValue是联动的.
例如给value设为1.5,intValue的值就是2.
另外,设置value和intValue的⽅法名字为display,⽽不是setValue或
者setIntValue.

digitCount

显⽰⼏位数字.

mode

数字显⽰形式.
1.QLCDNumber::Dec:⼗进制模式,显⽰常规的⼗进制数字。
2.QLCDNumber::Hex:⼗六进制模式,以⼗六进制格式显⽰数字。
3.QLCDNumber::Bin:⼆进制模式,以⼆进制格式显⽰数字。
4.QLCDNumber::Oct:⼋进制模式,以⼋进制格式显⽰数字。
只有⼗进制的时候才能显⽰⼩数点后的内容.

segmentStyle

设置显⽰⻛格.
1.QLCDNumber::Flat:平⾯的显⽰⻛格,数字呈现在⼀个平坦的表⾯上。
2.QLCDNumber::Outline:轮廓显⽰⻛格,数字具有清晰的轮廓和阴影效
果。
3.QLCDNumber::Filled:填充显⽰⻛格,数字被填充颜⾊并与背景区分开。

smallDecimalPoint

设置⽐较⼩的⼩数点.

3.2.2.1. 代码示例1:倒计时
  1. 在界面上创建一个QLCDNumber,初始值设置为5

  1. 修改widget.h和widget.cpp
#ifndefWIDGET_H
#defineWIDGET_H

#include<QWidget>

QT_BEGIN_NAMESPACE
namespaceUi{classWidget;}
QT_END_NAMESPACE

classWidget:publicQWidget
{
Q_OBJECT

public:
Widget(QWidget*parent=nullptr);
~Widget();

voidhandle();
privateslots:


private:
Ui::Widget*ui;
QTimer*timer;
};
#endif//WIDGET_H
#include"widget.h"
#include"ui_widget.h"

#include<QIcon>
#include<QRect>
#include<QPushButton>
#include<QDebug>
#include<QButtonGroup>
#include<QString>
#include<QResizeEvent>
#include<QSize>

#include<QTimer>

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

ui->lcdNumber->display("10");

timer=newQTimer(this);

connect(timer,&QTimer::timeout,this,&Widget::handle);

timer->start(1000);
}

Widget::~Widget()
{
deleteui;
}

voidWidget::handle()
{
intvalue=ui->lcdNumber->intValue();
if(value<=0)
{
timer->stop();
return;
}
ui->lcdNumber->display(value-1);
}

QTimer表示定时器,同故宫start方法启动定时器,就会每隔一定周期,触发一次QTimer::timeout信号。使用connect把QTimer::timeout信号和Widget::handle连接起来,意味着每次触发QTimer::timeout都会执行Widget::updateTime

  1. 执行程序


针对上面的代码,如果直接在构造函数中,通过一个循环+sleep的方式是否可以实现这个效果?

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

ui->lcdNumber->display("10");

timer=newQTimer(this);

//connect(timer,&QTimer::timeout,this,&Widget::handle);

//timer->start(1000);
intvalue=ui->lcdNumber->intValue();
while(true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
if(value<=0)
{
break;
}
ui->lcdNumber->display(value-1);
}
}

这个代码是不行的,循环会使Widget的构造函数无法执行完毕,此时界面是不能正确构造和现实的。


直接在构造函数里不行,另起一个线程,在新线程中完成这个操作可以吗?

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

ui->lcdNumber->display("10");

timer=newQTimer(this);

//connect(timer,&QTimer::timeout,this,&Widget::handle);

//timer->start(1000);
std::threadt([this](){
intvalue=this->ui->lcdNumber->intValue();
while(true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
if(value<=0)
{
break;
}
this->ui->lcdNumber->display(value-1);
}
});
}

这个代码同样不行,Qt中规定,任何对于GUI上内容的操作,必须在主线程中完成,像Widget构造函数,以及connect连接的slot函数,都是在主线程中调用的,而我们自己创建的线程则不是,当我们自己的线程中尝试对界面元素进行修改的时候,Qt程序往往会直接崩溃。

这样的约定主要是因为GUI中的状态往往是牵⼀发动全⾝的,修改⼀个地⽅,就需要同步的对其他内容进⾏调整.⽐如调整了某个元素的尺⼨,就可能影响到内部的⽂字位置,或者其他元素的位置.这⾥⼀连串的修改,都是需要按照⼀定的顺序来完成的.由于多线程执⾏的顺序⽆法保障,因此Qt从根本上禁⽌了其他线程修改GUI状态,避免后续的⼀系列问题.

3.2.3. ProgressBar(进度条)

使用QProgressBar表示一个进度条

注意,不要把ProgessBar拼写成ProcessBar

属性

说明

minimum

进度条最⼩值

maximum

进度条最⼤值

value

进度条当前值

alignment

⽂本在进度条中的对⻬⽅式.

•Qt::AlignLeft:左对⻬
•Qt::AlignRight:右对⻬
•Qt::AlignCenter:居中对⻬
•Qt::AlignJustify:两端对⻬

textVisible

进度条的数字是否可⻅.

orientation

进度条的⽅向是⽔平还是垂直

invertAppearance

是否是朝反⽅向增⻓进度

textDirection

⽂本的朝向.

format

展⽰的数字格式.
•%p:表⽰进度的百分⽐(0-100)
•%v:表⽰进度的数值(0-100)
•%m:表⽰剩余时间(以毫秒为单位)
•%t:表⽰总时间(以毫秒为单位)

3.2.3.1. 代码示例1:设置进度条按时间增长
  1. 在界面上创建进度条,objectName为progressBar

其中最小值设为0,最大值设为100

  1. 修改widget.h,创建QTimer和updateProgressBar函数
QT_BEGIN_NAMESPACE
namespaceUi{classWidget;}
QT_END_NAMESPACE

classWidget:publicQWidget
{
Q_OBJECT

public:
Widget(QWidget*parent=nullptr);
~Widget();


voidupdateProgressBa();


private:
Ui::Widget*ui;
QTimer*timer;
};
  1. 修改widget.cpp
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

timer=newQTimer(this);
connect(timer,&QTimer::timeout,this,&Widget::updateProgressBa);
timer->start(100);
}

Widget::~Widget()
{
deleteui;
}

voidWidget::updateProgressBa()
{
intvalue=ui->progressBar->value();
if(value>=100){
timer->stop();
}
else
{
ui->progressBar->setValue(value+1);
}
}
  1. 运行程序

在实际开发中,进度条的取值,往往是根据当前任务的实际进度来进⾏设置的.⽐如需要读取⼀个很⼤的⽂件,就可以获取⽂件的总的⼤⼩,和当前读取完毕的⼤⼩,来设置进度条的⽐例.由于上⾯我们介绍了Qt禁⽌在其他线程修改界⾯,因此进度条的更新往往也是需要搭配定时器来完成的.通过定时器周期触发信号,主线程调⽤对应的slot函数.再在slot函数中对当前的任务进度进⾏计算,并更新进度条的界⾯效果

3.2.4. CallendarWidget(日历)

QCalendarWidget表示一个"日历"

属性

说明

selectDate

当前选中的⽇期

minimumDate

最⼩⽇期

maximumDate

最⼤⽇期

firstDayOfWeek

每周的第⼀天(也就是⽇历的第⼀列)是周⼏.

gridVisible

是否显⽰表格的边框

selectionMode

是否允许选择⽇期

navigationBarVisible

⽇历上⽅标题是否显⽰

horizontalHeaderFormat

⽇历上⽅标题显⽰的⽇期格式

verticalHeaderFormat

⽇历第⼀列显⽰的内容格式

dateEditEnabled

是否允许⽇期被编辑


重要信号

信号

说明

selectionChanged(const
QDate&)

当选中的⽇期发⽣改变时发出

activated(constQDate&)

当双击⼀个有效的⽇期或者按下回⻋键时发出,形参是⼀个QDate类型,保存
了选中的⽇期

currentPageChanged(int,
int)

当年份⽉份改变时发出,形参表⽰改变后的新年份和⽉份

3.2.4.1. 代码示例1:获取选中的日期
  1. 在界面上创建一个QCalendarWidget和一个label

objectName为calendarWidget,label

  1. 给QCalendarWidget添加槽函数
voidWidget::on_calendarWidget_selectionChanged()
{
QDatedate=ui->calendarWidget->selectedDate();
ui->label->setText(date.toString());
}
  1. 执行程序

3.3. 输入类控件

3.3.1. LineEdit(单行输入)

QLineEdit用来表示单行输入框,可以输入一段文本,但是不能换行。

属性

说明

text

输⼊框中的⽂本

inputMask

输⼊内容格式约束

maxLength

最⼤⻓度

frame

是否添加边框

echoMode

显⽰⽅式.
•QLineEdit::Normal:这是默认值,⽂本框会显⽰输⼊的⽂本。
•QLineEdit::Password:在这种模式下,输⼊的字符会被隐藏,通常⽤星号(*)或等号(=)代替。
•QLineEdit::NoEcho:在这种模式下,⽂本框不会显⽰任何输⼊
的字符。

cursorPosition

光标所在位置

alignment

⽂字对⻬⽅式,设置⽔平和垂直⽅向的对⻬.

dragEnabled

是否允许拖拽

readOnly

是否是只读的(不允许修改)

placeHolderText

当输⼊框内容为空的时候,显⽰什么样的提⽰信息

clearButtonEnabled

是否会⾃动显⽰出"清除按钮".

重要信号

属性

说明

voidcursorPositionChanged(intold,intnew)

当⿏标移动时发出此信号,old为先前的位置,new为新位置。

voideditingFinished()

当按返回或者回⻋键时,或者⾏编辑失去焦点时,发出此信号。

voidreturnPressed()

当返回或回⻋键按下时发出此信号.如果设置了验证器,必须要验证通过,才能触发.

voidselectionChanged()

当选中的⽂本改变时,发出此信号。

voidtextChanged(constQString&text)

当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。代码对⽂本的修改能够触发这个信号.

voidtextEdited(constQString&text))

当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。代码对⽂本的修改不能触发这个信号.

3.3.1.1. 代码示例1:录入个人信息
  1. 在界⾯上创建三个输⼊框和两个单选按钮,⼀个普通按钮,三个输入框的objectName为lineEdit_name/password/phone,两个单选按钮objectName为radioButton_male,radioButton_female按钮的objectName为pushButton


2.修改widget.cpp

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
ui->lineEdit_name->setPlaceholderText("Pleaseenterthename");
ui->lineEdit_name->setClearButtonEnabled(true);

ui->lineEdit_password->setEchoMode(QLineEdit::Password);
ui->lineEdit_password->setClearButtonEnabled(true);

ui->lineEdit_phone->setPlaceholderText("Pleaseenterthephonenumber");
ui->lineEdit_phone->setClearButtonEnabled(true);
ui->lineEdit_phone->setInputMask("000-0000-0000");
}
  1. 添加slot函数
voidWidget::on_pushButton_clicked()
{
QStringgender=ui->radioButton_male->isChecked()?"男":"女";

qDebug()<<"name:"<<ui->lineEdit_name->text();
qDebug()<<"pwd:"<<ui->lineEdit_password->text();
qDebug()<<"sex:"<<gender;
qDebug()<<"phone:"<<ui->lineEdit_phone->text();
}
  1. 执行

inputMask只能进⾏简单的输⼊格式校验.实际开发中,基于正则表达式的⽅式是更核⼼的⽅法.

3.3.1.2. 代码示例2:使用正则表达式验证输入框的数据

次数要求在输入框中输入一个合法的电话号发(1开头,11位全是数字),如果格式不正确,则确定按钮无法点击。

关于正则表达式
正则表达式是⼀种在计算机中常⽤的,使⽤特殊字符描述⼀个字符串的特征的机制.在进⾏字
符串匹配时⾮常有⽤.
正则表达式的语法还⽐较复杂,⼀般都是随⽤随查,不需要背下来.

\A:表示从字符串的开始处匹配
\Z:表示从字符串的结束处匹配,如果存在执行,只匹配到换行前的结束字符串
\b:匹配一个单词边界,也就是说指单词和空格间的位置。
\B:匹配非单词边界。
\d:匹配任意数字,等价于---[0-9]
\D:匹配任意非数字字符,等价于---[^\d]
\s:匹配任意空白字符,等价于---[\t\n\r\f]
\S:匹配任意非空白字符,等价于---[^\s]
\w:匹配任意字母数字及下划线,等价于---[a-zA-Z0-9]
\W:匹配任意非字母数字及下划线,等价于---[^\w]
\\:匹配原义的反斜杠\
---------------------------------------
[]:用于表示一组字符,如果^事第一个字符,则表示的是一个补集,比如[0-9]表示所有的数字,[^0-9]表示除了数字外的字符
.:用于匹配除换行符之外的所有字符
^:用于匹配字符串的开始.及行首
$:用于匹配字符串的末尾(末尾如果有换行符,就匹配换行符前面的那个字符),及行尾
*:用于将前面的模式匹配0次或多次(贪婪模式,及尽可能多的匹配)
+:用于将前面的模式匹配1次或多次(贪婪模式)
?:用于将前面的模式匹配0次或1次(贪婪模式)
*?,+?,??是上面三种特殊字符的非贪婪模式(尽可能少的匹配)
{m}:用于验证将前面的模式匹配m次
{m,}:用于验证将前面的模式匹配m次或者多次--->>=m次
{m,n}:用于将前面的模式匹配m次到n次(贪婪模式),即最小匹配m次,最大匹配n次
{m,n}?即上面{m,n}的非贪婪模式
\\:\是转义字符,在特殊字符前面加上\,特殊字符就失去了其所代表的含义,比如\+就仅仅代表加号本身
|:比如A|B用于匹配A或B

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

QRegExpregExp("^1\\d{10}$");//创建一个正则对象,
//^表示匹配字符串的开始位置
//1表示匹配数字1
//\d表示匹配任意数字
//{10}表示重复匹配十次前面的模式
//$表示匹配字符串的结束位置
ui->lineEdit->setValidator(newQRegExpValidator(regExp));
//设置一个验证器

ui->pushButton->setEnabled(false);
}

Widget::~Widget()
{
deleteui;
}

//on_lineEdit_textEdited的参数是当前输⼊框的内容.
voidWidget::on_lineEdit_textEdited(constQString&arg1)
{
QStringcontent=arg1;
intpos=0;
//通过lineEdit->validator()获取到内置的验证器.
//过validate⽅法验证⽂本是否符合要求.
//◦第⼀个参数填写的是要验证的字符串.由于参数要求是QString&⽽不是const
//QString&,需要把这个变量复制⼀下.
//◦第⼆个参数是⼀个int&,是输出型参数.当验证的字符串不匹配时,返回这个字符串的⻓度.(没有
//啥实质作⽤).
//返回值是⼀个枚举.QValidator::Acceptable表⽰验证通过,
//QValidator::Invalid表⽰验证不通过.
if(ui->lineEdit->validator()->validate(content,pos)==QValidator::Acceptable)
{
ui->pushButton->setEnabled(true);
}
else
{
ui->pushButton->setEnabled(false);
}
}

3.3.1.3. 代码示例3:切换显示密码
  1. 创建一个输入框和一个复选按钮

  1. 修改widget.cpp
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

ui->lineEdit->setEchoMode(QLineEdit::Password);
}

Widget::~Widget()
{
deleteui;
}


voidWidget::on_checkBox_toggled(boolchecked)
{
if(checked){
ui->lineEdit->setEchoMode(QLineEdit::Normal);
}else{
ui->lineEdit->setEchoMode(QLineEdit::Password);
}
}
  1. 执行程序

3.3.2. TextEdit(多行输入)

QTextEdit表示多行输入框,也是一个富文本&markdown编辑器,并且能在内容超出编辑框范围时,自动提供滚动条。

属性

说明

markdown

输⼊框内持有的内容.⽀持markdown格式.能够⾃动的对markdown⽂本进⾏渲染成html

html

输⼊框内持有的内容.可以⽀持⼤部分html标签.包括img和table等.

placeHolderText

输⼊框为空时提⽰的内容.

readOnly

是否是只读的

undoRedoEnable

是否开启undo/redo功能.
按下ctrl+z触发undo
按下ctrl+y触发redo

autoFormating

开启⾃动格式化.

tabstopWidth

按下缩进占多少空间

overwriteMode

是否开启覆盖写模式

acceptRichText

是否接收富⽂本内容

verticalScrollBarPolicy

垂直⽅向滚动条的出现策略
Qt::ScrollBarAsNeeded:根据内容⾃动决定是否需要滚动条。这是默认值。
Qt::ScrollBarAlwaysOff:总是关闭滚动条。

Qt::ScrollBarAlwaysOn:总是显⽰滚动条。

horizontalScrollBarPolicy

⽔平⽅向滚动条的出现策略
Qt::ScrollBarAsNeeded:根据内容⾃动决定是否需要滚动条。这是默认
值。
Qt::ScrollBarAlwaysOff:总是关闭滚动条。
Qt::ScrollBarAlwaysOn:总是显⽰滚动条。

核心信号

信号

说明

textChanged()

⽂本内容改变时触发

selectionChanged()

选中范围改变时触发

cursorPositionChanged()

光标移动时触发

undoAvailable(bool)

可以进⾏undo操作时触发

redoAvailable(bool)

可以进⾏redo操作时触发

copyAvaiable(bool)

⽂本被选中/取消选中时触发

3.3.2.1. 代码示例1:获取多行输入框的内容
  1. 创建一个多行输入框和一个label


2.给多行输入框添加slot函数,处理textChanged信号

通过toPlainText方法获取到内部的文本

类似的,QTextEdit还提供了toMarkdown和toHtml,根据需要我们调整不同的获取方式。

voidWidget::on_textEdit_textChanged()
{
constQString&text=ui->textEdit->toPlainText();
ui->label->setText(text);
}
  1. 执行代码,就可以看到输入框中内容发生变化的时候,label也会同步发生变化。

3.3.3. ComboBox(下拉框)

QComboBox表示下拉框

重要属性

属性

说明

currentText

当前选中的⽂本

currentIndex

当前选中的条⽬下标.从0开始计算.如果当前没有条⽬被选中,值为-1

editable

是否允许修改
设为true时,QComboBox的⾏为就⾮常接近QLineEdit,也可以设置validator

iconSize

下拉框图标(⼩三⻆)的⼤⼩

maxCount

最多允许有多少个条⽬

重要方法

⽅法

说明

addItem(constQString&)

添加⼀个条⽬

currentIndex()

获取当前条⽬的下标
从0开始计算.如果当前没有条⽬被选中,值为-1

currentText()

获取当前条⽬的⽂本内容.

重要信号

⽅法

说明

activated(int)
activated(constQString&text)

当⽤⼾选择了⼀个选项时发出.
这个时候相当于⽤⼾点开下拉框,并且⿏标划过某个选项.
此时还没有确认做出选择.

currentIndexChanged(int)
currentIndexChanged(constQString
&text)

当前选项改变时发出.
此时⽤⼾已经明确的选择了⼀个选项.
⽤⼾操作或者通过程序操作都会触发这个信号.

editTextChanged(constQString&
text)

当编辑框中的⽂本改变时发出
(editable为true时有效)

3.3.3.1. 代码示例1:使用下拉框模拟点餐
  1. 在界面上创建三个下拉框,和一个按钮

  1. 修改widget.cpp
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
ui->comboBox_1->addItem("炒面");
ui->comboBox_1->addItem("炒米");

ui->comboBox_2->addItem("薯条");
ui->comboBox_2->addItem("可比克");

ui->comboBox_3->addItem("可乐");
ui->comboBox_3->addItem("雪碧");
}

Widget::~Widget()
{
deleteui;
}

voidWidget::on_pushButton_clicked()
{
qDebug()<<ui->comboBox_1->currentText();
qDebug()<<ui->comboBox_2->currentText();
qDebug()<<ui->comboBox_3->currentText();
}
  1. 执行程序

3.3.3.2. 代码示例2:从文件中加载下拉框的选项
  1. 在界面上创建一个下拉框

  1. 创建文件d:/config.txt,编写选项,每个选项占一行

  1. 修改widget.cpp
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

//读取文件内容,把文件中的每一行读取出来,作为comboBox的内容
std::ifstreamfile("D:/code_qt/test/untitled1/config.txt");
if(!file.is_open()){
qDebug()<<"filefail";
return;
}

//按行读取文本内容
std::stringline;
while(std::getline(file,line))
{
ui->comboBox->addItem(QString::fromStdString(line));
}

file.close();

}
  1. 执行程序,就可以看到效果了

3.3.4. SpinBox(微调框)

使⽤QSpinBox或者QDoubleSpinBox表⽰"微调框",它是带有按钮的输⼊框.可以⽤来输⼊整数/浮点数.通过点击按钮来修改数值⼤⼩.

由于SpinBox和QDoubleSpinBox⽤法基本相同,就只介绍SpinBox的使⽤了

常用属性

属性

说明

value

存储的数值.

singleStep

每次调整的"步⻓".按下⼀次按钮数据变化多少.

displayInteger

数字的进制.例如displayInteger设为10,则是按照10进制表⽰.设为2则为2进制表⽰.

minimum

最⼩值

maximum

最⼤值

suffix

后缀

prefix

前缀

wrapping

是否允许换⾏

frame

是否带边框

alignment

⽂字对⻬⽅式.

readOnly

是否允许修改

buttonSymbol

按钮上的图标.

UpDownArrows上下箭头形式
PlusMinus加减号形式
NoButtons没有按钮

accelerated(加速的)

按下按钮时是否为快速调整模式

correctionMode


 

输⼊有误时如何修正.
QAbstractSpinBox::CorrectToPreviousValue:如果⽤⼾输⼊了⼀个⽆效的值(例如,在只能显⽰正整数的SpinBox中输⼊了负数),那么SpinBox会恢复为上⼀个有效值。例如,如果SpinBox的初始值是1,⽤⼾输⼊了-1(⽆效),然后SpinBox会恢复为1。
QAbstractSpinBox::CorrectToNearestValue:如果⽤⼾输⼊了⼀个⽆效的值,SpinBox会恢复为最接近的有效值。例如,如果SpinBox的初始值是1,⽤⼾输⼊了-1(⽆效),那么SpinBox会恢复为0。

keyboardTrack


 

是否开启键盘跟踪.
设为true,每次在输⼊框输⼊⼀个数字,都会触发⼀次valueChanged()和textChanged()信号.设为false,只有在最终按下enter或者输⼊框失去焦点,才会触发
valueChanged()和textChanged()信号.

常用信号

信号

说明

textChanged(QString)

微调框的⽂本发⽣改变时会触发.参数QString带有前缀和后缀.

valueChanged(int)

微调框的⽂本发⽣改变时会触发.参数int,表⽰当前的数值.

3.3.4.1. 代码示例1:调正购物车中的份数
  1. 在界面中创建三个下拉框,三个微调框,一个按钮

  1. 修改widget.cpp
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

ui->spinBox->setValue(1);
ui->spinBox->setRange(1,99);
ui->spinBox_2->setValue(1);
ui->spinBox_2->setRange(1,99);
ui->spinBox_3->setValue(1);
ui->spinBox_3->setRange(1,99);

}

Widget::~Widget()
{
deleteui;
}

voidWidget::on_pushButton_clicked()
{
qDebug()<<ui->comboBox_1->currentText()<<""<<ui->spinBox->value();
qDebug()<<ui->comboBox_2->currentText()<<""<<ui->spinBox_2->value();
qDebug()<<ui->comboBox_3->currentText()<<""<<ui->spinBox_3->value();
}
  1. 执行代码

3.3.5. DateEdit&TimeEdit&DateTimeEdit(日期&时间&时间日期的微调框)

使用QDateEdit作为日期的微调框,使用QTimeEdit作为时间的微调框,QDateTimeEdit作为时间日期的微调框

以QDateTimeEdit为例进行介绍

常用属性

属性

说明

dateTime

时间⽇期的值.形如2000/1/10:00:00

date

单纯⽇期的值.形如2001/1/1

time

单纯时间的值.形如0:00:00

displayFormat

时间⽇期格式.形如yyyy/M/dH:mm
•y表⽰年份
•M表⽰⽉份
•d表⽰⽇期
•H表⽰⼩时
•m表⽰分钟
•s表⽰秒
注意:这⾥的格式化符号的含义,不要记忆.不同语⾔/库的设定规则
是存在差异的.⼀定是⽤的时候再去查.

minimumDateTime

最⼩时间⽇期

maximumDateTime

最⼤时间⽇期

timeSpec

•Qt::LocalTime:显⽰本地时间。
•Qt::UTC:显⽰协调世界时(UTC)。
•Qt::OffsetFromUTC:显⽰相对于UTC的偏移量(时差).

常用信号

信号

说明

dateChanged(QDate)

⽇期改变时触发.

timeChanged(QTime)

时间改变时触发.

dateTimeChanged(QDateTi
me)

时间⽇期任意⼀个改变时触发.

3.3.5.1. 代码示例1:实现日期计算器
  1. 在界面上创建两个QDateTimeEdit和一个按钮,一个label,objectName为dateTimeEdit_old/new

  1. 修改widget.cpp

使⽤daysTo函数可以计算两个⽇期的天数.
使⽤secsTo函数可以计算两个时间的秒数.
通过(秒数/3600)换算成⼩时数,再余上24得到零⼏个⼩时.
使⽤QString::number把整数转成QString进⾏拼接.

Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

}

Widget::~Widget()
{
deleteui;
}



voidWidget::on_pushButton_clicked()
{
//获取日期
QDateTimetimeOld=ui->dateTimeEdit_old->dateTime();
QDateTimetimeNew=ui->dateTimeEdit_new->dateTime();

qDebug()<<timeOld<<timeNew;

//计算天数
intdays=timeOld.daysTo(timeNew);
qDebug()<<days;

//计算秒
intseconds=timeOld.secsTo(timeNew);

//转换成小时
inthours=(seconds/3600)%24;

//把计算结果放到label中
ui->label->setText(QString("时间过了")+QString::number(days)+"天零"+QString::number(hours)+QString("小时"));
}
  1. 执行程序

3.3.6. Dial(旋钮)

使用QDial表示一个旋钮

常用属性

属性

说明

value

持有的数值.

minimum

最⼩值

maximum

最⼤值

singleStep

按下⽅向键的时候改变的步⻓.

pageStep

按下pageUp/pageDown的时候改变的步⻓.

sliderPosition

界⾯上旋钮显⽰的初始位置

tracking

外观是否会跟踪数值变化.
默认值为true.⼀般不需要修改.

wrapping

是否允许循环调整.
即数值如果超过最⼤值,是否允许回到最⼩值.
(调整过程能否"套圈")

notchesVisible

是否显⽰刻度线

notchTarget

刻度线之间的相对位置.
数字越⼤,刻度线越稀疏.

常用信号

属性

说明

valueChanged(int)

数值改变时触发

rangeChanged(int,int)

范围变化时触发

3.3.6.1. 代码示例1:调整窗口透明度
  1. 在界面上创建一个旋钮和一个label

  1. 修改eidget.cpp
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

}

Widget::~Widget()
{
deleteui;
}

voidWidget::on_dial_valueChanged(intvalue)
{
qDebug()<<value;
this->setWindowOpacity((double)value/100);
ui->label->setText("当前不透明度:"+QString::number(value/100));
}
  1. 运行程序

3.3.7. Slider(滑动条)

使用QSlider表示一个滑动条

🏝QSlider和QDial都是继承⾃QAbstractSlider,因此⽤法上基本相同.

常用属性

属性

说明

value

持有的数值.

minimum

最⼩值

maximum

最⼤值

singleStep

按下⽅向键的时候改变的步⻓.

pageStep

按下pageUp/pageDown的时候改变的步⻓.

sliderPosition

滑动条显⽰的初始位置

tracking

外观是否会跟踪数值变化.
默认值为true.⼀般不需要修改.

orientation

滑动条的⽅向是⽔平还是垂直

invertedAppearance

是否要翻转滑动条的⽅向

tickPosition

刻度的位置.

tickInterval

刻度的密集程度.

常用信号

属性

说明

valueChanged(int)

数值改变时触发

rangeChanged(int,int)

范围变化时触发

3.3.7.1. 代码示例1:
  1. 在界面上创建两个滑动条,分别是水平和垂直滑动条objectNmae为horizeontalSlider和verticalSlider

  2. 编写代码
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);

ui->horizontalSlider->setMinimum(100);
ui->horizontalSlider->setMaximum(2000);
ui->horizontalSlider->setValue(800);
ui->horizontalSlider->setSingleStep(50);

ui->verticalSlider->setMinimum(100);
ui->verticalSlider->setMaximum(1500);
ui->verticalSlider->setValue(600);
ui->verticalSlider->setSingleStep(50);
}

Widget::~Widget()
{
deleteui;
}

voidWidget::on_horizontalSlider_valueChanged(intvalue)
{
constQRect&rect=this->geometry();
this->setGeometry(rect.x(),rect.y(),value,rect.height());
}



voidWidget::on_verticalSlider_valueChanged(intvalue)
{
constQRect&rect=this->geometry();
this->setGeometry(rect.x(),rect.y(),rect.width(),value);
}
  1. 执行程序,可以通过调整滑动条改变窗口大小

3.4. 多元素控件

Qt中提供的多元素控件有

  1. QListWidget
  2. QListView
  3. QTableWidget
  4. QTableView
  5. QTreeWidget
  6. QTreeView

xxWidget和xxView之间的区别
以QTableWidget和QTableView为例.
QTableView是基于MVC设计的控件.QTableView⾃⾝不持有数据.使⽤QTableView的时候需要⽤⼾创建⼀个Model对象(⽐如QStandardModel),并且把Model和
QTableView关联起来.后续修改Model中的数据就会影响QTableView的显⽰;修改
QTableView的显⽰也会影响到Model中的数据(双向绑定).
QTableWidget则是QTableView的⼦类,对Model进⾏了封装.不需要⽤⼾⼿动创建
Model对象,直接就可以往QTableWidget中添加数据了.

3.4.1. ListWidget(纵向的列表)

使用QListWidget能够显示一个纵向的列表,每个选项都可以被选中

常用属性

属性

说明

currentRow

当前被选中的是第⼏⾏

count

⼀共有多少⾏

sortingEnabled

是否允许排序

isWrapping

是否允许换⾏

itemAlignment

元素的对⻬⽅式

selectRectVisible

被选中的元素矩形是否可⻅

spacing

元素之间的间隔

常用方法

⽅法

说明

addItem(constQString&label)
addItem(QListWidgetItem*item)

列表中添加元素.

currentItem()

返回QListWidgetItem*表⽰当前选中的元素

setCurrentItem(QListWidgetItem*item)

设置选中哪个元素

setCurrentRow(introw)

设置选中第⼏⾏的元素

insertItem(constQString&label,int
row)
insertItem(QListWidgetItem*item,int
row)

在指定的位置插⼊元素

item(introw)

返回QListWidgetItem*表⽰第row⾏的元素

takeItem(introw)

删除指定⾏的元素,返回QListWidgetItem*表⽰是哪个元素被删除了

常用信号

⽅法

说明

currentItemChanged(QListWidgetItem*current,QListWidgetItem*old)

选中不同元素时会触发.参数是当前选中的元素和之前选中的元素.

currentRowChanged(int)

选中不同元素时会触发.参数是当前选中元素的⾏数.

itemClicked(QListWidgetItem*item)

点击某个元素时触发

itemDoubleClicked(QListWidgetItem*
item)

双击某个元素时触发

itemEntered(QListWidgetItem*item)

⿏标进⼊元素时触发


在上述介绍中,设计到一个关键的类,QListWidgetItem,这个类表示QListWidget中的一个元素

常用方法如下,本质上就是一个"文本+图标"构成的。

⽅法

说明

setFont

设置字体

setIcon

设置图标

setHidden

设置隐藏

setSizeHint

设置尺⼨

setSelected

设置是否选中

setText

设置⽂本

setTextAlignment

设置⽂本对⻬⽅式.


 

3.4.1.1. 代码示例1:使用ListWidget
  1. 在界面上创建一个ListView,右键变形为ListWidget,在创建一个lineEdit和两个按钮,

ListWidget是ListView的子类,功能比ListView更丰富

  1. 编写widget.cpp
Widget::Widget(QWidget*parent)
:QWidget(parent)
,ui(newUi::Widget)
{
ui->setupUi(this);
ui->listWidget->addItem("C/C++");
ui->listWidget->addItem("Python");
ui->listWidget->addItem("php");
}

Widget::~Widget()
{
deleteui;
}


voidWidget::on_pushButton_add_clicked()
{
//1.先获取到输入框中的内容
constQString&text=ui->lineEdit->text();
//2.添加到listwidget中
ui->listWidget->addItem(text);
}

voidWidget::on_pushButton_del_clicked()
{
//1.先获取到被选中的元素是哪个
introw=ui->listWidget->currentRow();
if(row<0){
return;
}
ui->listWidget->takeItem(row);
}
  1. 执行程序


 

3.4.2. TableWidget(表格控件)

使用QTableWidget表示一个表格控件,一个表格中包含若干行,每一行又包含若干列,表格中的每个单元格,是一个QTableWidgetItem对象

常用方法

⽅法

说明

item(introw,intcolumn)

根据⾏数列数获取指定的QTableWidgetItem*

setItem(introw,intc
QTableWidget*)

根据⾏数列数设置表格中的元素

currentItem()

返回被选中的元素QTableWidgetItem*

currentRow()

返回被选中元素是第⼏⾏

currentColumn()

返回被选中元素是第⼏列

row(QTableWidgetItem*)

获取指定item是第⼏⾏

column(QTableWidgetItem*)

获取指定item是第⼏列

rowCount()

获取⾏数

columnCount()

获取列数

insertRow(introw)

在第row⾏处插⼊新⾏

insertColumn(intcolumn)

在第column列插⼊新列

removeRow(introw)

删除第row⾏

removeColumn(intcolumn)

删除第column列

setHorizontalHeaderItem(int
column,QTableWidget*)

设置指定列的表头

setVerticalHeaderItem(introw,
QTableWidget*)

设置指定⾏的表头

常用信号

信号

说明

cellClicked(introw,intcolumn)

点击单元格时触发

cellDoubleClicked(introw,int
column)

双击单元格时触发

cellEntered(introw,intcolumn)

⿏标进⼊单元格时触发

currentCellChanged(introw,int
column,intpreviousRow,int
previousColumn)

选中不同单元格时触发

QTableWidgetItem常用方法

⽅法

说明

row()

获取当前是第⼏⾏

column()

获取当前是第⼏列

setText(constQString&)

设置⽂本

setTextAlignment(int)

设置⽂本对⻬

setIcon(constQIcon&)

设置图标

setSelected(bool)

设置被选中

setSizeHints(constQSize&)

设置尺⼨

setFont(constQFont&)

设置字体

3.4.2.1. 代码示例1:使用QTableWidget
  1. 在界面上创建QTableWidget和三个按钮,一个输入框

  1. 编写Widget,cpp函数
#include "widget.h"
#include "ui_widget.h"

#include <QIcon>
#include <QRect>
#include <QPushButton>
#include <QDebug>
#include <QButtonGroup>
#include <QString>
#include <QResizeEvent>
#include <QSize>
#include <thread>
#include <QRegExp>
#include <QRegExpValidator>

#include <fstream>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 创建3行
    for (int i = 0; i < 3; i++)
    {
        ui->tableWidget->insertRow(i);
    }
    //  创建3列
    for (int i = 0; i < 3; i++)
    {
        ui->tableWidget->insertColumn(i);
    }

    // 给3列设定列明
    ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("sno"));
    ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("name"));
    ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("age"));

    // 设置初始数据
    ui->tableWidget->setItem(0, 0, new QTableWidgetItem("1001"));
    ui->tableWidget->setItem(0, 1, new QTableWidgetItem("张三"));
    ui->tableWidget->setItem(0, 2, new QTableWidgetItem("15"));


    ui->tableWidget->setItem(1, 0, new QTableWidgetItem("1002"));
    ui->tableWidget->setItem(1, 1, new QTableWidgetItem("李四"));
    ui->tableWidget->setItem(1, 2, new QTableWidgetItem("16"));

    ui->tableWidget->setItem(2, 0, new QTableWidgetItem("1003"));
    ui->tableWidget->setItem(2, 1, new QTableWidgetItem("王五"));
    ui->tableWidget->setItem(2, 2, new QTableWidgetItem("17"));
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_add_row_clicked()
{
    // 获取到行数
    int rowCount = ui->tableWidget->rowCount();
    // 插入新行
    ui->tableWidget->insertRow(rowCount);
}

void Widget::on_pushButton_add_col_clicked()
{
    int curRow = ui->tableWidget->columnCount();
    ui->tableWidget->insertColumn(curRow);
}

void Widget::on_pushButton_del_row_clicked()
{
    int curRow = ui->tableWidget->currentRow();
    // 删除对应行
    ui->tableWidget->removeRow(curRow);
}

void Widget::on_pushButton_del_col_clicked()
{
    int curRow = ui->tableWidget->currentColumn();
    ui->tableWidget->removeColumn(curRow);
}
  1. 执行代码就可以操作表格了

3.4.3. TreeWidget(树形控件)

使⽤ QTreeWidget 表⽰⼀个树形控件.⾥⾯的每个元素,都是⼀个 QTreeWidgetItem ,每个
QTreeWidgetItem 可以包含多个⽂本和图标,每个⽂本/图标为⼀个列.可以给QTreeWidget 设置顶层节点(顶层节点可以有多个),然后再给顶层节点添加⼦节点,从⽽构成树形结构.

方法

说明

clear

清空所有子节点

addTopLevelItem(QTreeWidgetItem*item)

新增顶层节点

topLevelItem(intindex)

获取指定下标的顶层节点.

topLevelItemCount()

获取顶层节点个数

indexOfTopLevelItem(QTreeWidgetItem*
item)

查询指定节点是顶层节点中的下标

takeTopLevelItem(intindex)

删除指定的顶层节点.返回QTreeWidgetItem*表⽰被删除
的元素

currentItem()

获取到当前选中的节点,返回QTreeWidgetItem*

setCurrentItem(QTreeWidgetItem*item)

选中指定节点

setExpanded(bool)

展开/关闭节点

setHeaderLabel(constQString&text)

设置TreeWidget的header名称.

常用信号

信号

说明

currentItemChanged(QTreeWidgetItem*
current,QTreeWidgetItem*old)

切换选中元素时触发

itemClicked(QTreeWidgetItem*item,intcol)

点击元素时触发

itemDoubleClicked(QTreeWidgetItem*item,
intcol)

双击元素时触发

itemEntered(QTreeWidgetItem*item,intcol)

⿏标进⼊时触发

itemExpanded(QTreeWidgetItem*item)

元素被展开时触发

itemCollapsend(QTreeWidgetItem*item)

元素被折叠时触发

QTreeWidgetItem 核⼼属性

属性

说明

text

持有的文本

textAlignment

文本对齐方式

icon

持有的图表

font

⽂本字体

hidden

是否隐藏

disabled

是否禁⽤

expand

是否展开

sizeHint

尺⼨⼤⼩

selected

是否选中

QTreeWidgetItem 核⼼⽅法

⽅法

说明

addChild(QTreeWidgetItem*child)

新增⼦节点

childCount()

⼦节点的个数

child(intindex)

获取指定下标的⼦节点.返回QTreeWidgetItem*

takeChild(intindex)

删除对应下标的⼦节点

removeChild(QTreeWidgetItem*
child)

删除对应的⼦节点

parent()

获取该元素的⽗节点

3.4.3.1. 代码示例1:QTreeWidget
  1. 在界面上创建一个TreeWidget,在创建一个lineEdit和两个按钮

  1. 编写代码,构造初始数据
#include "widget.h"
#include "ui_widget.h"

#include <QIcon>
#include <QRect>
#include <QPushButton>
#include <QDebug>
#include <QButtonGroup>
#include <QString>
#include <QResizeEvent>
#include <QSize>
#include <thread>
#include <QRegExp>
#include <QRegExpValidator>

#include <fstream>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->treeWidget->setHeaderLabel("动物");

    QTreeWidgetItem* item1 = new QTreeWidgetItem();
    item1->setText(0, "猫");
    ui->treeWidget->addTopLevelItem(item1);

    QTreeWidgetItem* item2 = new QTreeWidgetItem();
    item2->setText(0, "狗");
    ui->treeWidget->addTopLevelItem(item2);

    QTreeWidgetItem* item3 = new QTreeWidgetItem();
    item3->setText(0, "鸟");
    ui->treeWidget->addTopLevelItem(item3);
}

Widget::~Widget()
{
    delete ui;
}



void Widget::on_pushButton_clicked()
{
    const QString& text = ui->lineEdit->text();
    if (text.isEmpty())
    {
        return;
    }
    QTreeWidgetItem* item = new QTreeWidgetItem();
    item->setText(0, text);
    ui->treeWidget->addTopLevelItem(item);
}

void Widget::on_pushButton_2_clicked()
{
    const QString& text = ui->lineEdit->text();
    if (text.isEmpty())
    {
        return;
    }

    QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();
    if (currentItem == nullptr) {
        return;
    }

    QTreeWidgetItem* newItem = new QTreeWidgetItem();
    newItem->setText(0, text);
    currentItem->addChild(newItem);
    currentItem->setExpanded(true);
}

void Widget::on_pushButton_3_clicked()
{
    QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();
    if (currentItem == nullptr) {
        return;
    }

    QTreeWidgetItem* parent = currentItem->parent();
    if (parent == nullptr) {
        int index = ui->treeWidget->indexOfTopLevelItem(currentItem);
        ui->treeWidget->takeTopLevelItem(index);
    }
    else {
        parent->removeChild(currentItem);
    }
}
  1. 执行代码

3.5. 容器类控件

3.5.1. GroupBox(分组框)

使⽤ QGroupBox 实现⼀个带有标题的分组框.可以把其他的控件放到⾥⾯作为⼀组.这样看起来能更好看⼀点.
 


常用属性

属性

说明

title

分组框的标题

alignment

分组框内部内容的对⻬⽅式

flat

是否是"扁平"模式

checkable

是否可选择.
设为true,则在title前⽅会多出⼀个可勾选的部分.

checked

描述分组框的选择状态(前提是checkable为true)

分组框只是⼀个⽤来"美化界⾯"这样的组件,并不涉及到⽤⼾交互和业务逻辑.属于"锦上添
花".

3.5.1.1. 代码示例1:给麦当劳案例加上分组框
  1. 在界面上创建三个分组框,并且在分组框内部创建下拉框和微调框

  1. 在ui中设置一些属性

  1. 运行代码,这就是分组框的作用。

3.5.2. TabWidget(带有标签页的控件)

使⽤ QTabWidget 实现⼀个带有标签⻚的控件,可以往⾥⾯添加⼀些widget.进⼀步的就可以通过标签⻚来切换.
 

常用属性

属性

说明

tabPosition

标签⻚所在的位置.
• North 上⽅
• South 下⽅
• West 左侧
• East 右侧

currentIndex

当前选中了第⼏个标签⻚(从0开始计算)

currentTabText

当前选中的标签⻚的⽂本

currentTabName

当前选中的标签⻚的名字

currentTabIcon

当前选中的标签⻚的图标

currentTabToolTip

当前选中的标签⻚的提⽰信息

tabsCloseable

标签⻚是否可以关闭

movable

标签⻚是否可以移动


常用信号

属性

说明

currentChanged(int)

在标签⻚发⽣切换时触发,参数为被点击的选项卡编号.

tabBarClicked(int)

在点击选项卡的标签条的时候触发.参数为被点击的选项卡编号.

tabBarDoubleClicked(int)

在双击选项卡的标签条的时候触发.参数为被点击的选项卡编号.

tabCloseRequest(int)

在标签⻚关闭时触发.参数为被关闭的选项卡编号.

3.5.2.1. 代码示例1:使用标签页管理多组控件
  1. 在界面上创建一个QTabWideget,和两个按钮,objectName为pushButton_add/del

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QLabel* label = new QLabel(ui->tab);
    label->setText("标签页1");
//    label->resize(100, 50);
    QLabel* label2 = new QLabel(ui->tab_2);
    label2->setText("标签页2");

}
  1. 编写slot函数

使⽤ count() 获取到标签⻚的个数.
使⽤ addTab 新增标签⻚.
使⽤ removeTab 删除标签⻚.
使⽤ currentIndex 获取到当前标签⻚的下标.
使⽤ setCurrentIndex 切换当前标签⻚.

#include "widget.h"
#include "ui_widget.h"

#include <QIcon>
#include <QRect>
#include <QPushButton>
#include <QDebug>
#include <QButtonGroup>
#include <QString>
#include <QResizeEvent>
#include <QSize>
#include <thread>
#include <QRegExp>
#include <QRegExpValidator>
#include <QLabel>

#include <fstream>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QLabel* label = new QLabel(ui->tab);
    label->setText("标签页1");
//    label->resize(100, 50);
    QLabel* label2 = new QLabel(ui->tab_2);
    label2->setText("标签页2");

}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_add_clicked()
{
    int cnt = ui->tabWidget->count();

    QWidget* w = new QWidget();
    ui->tabWidget->addTab(w, QString("Tab ") + QString::number(cnt + 1));
    QLabel* label = new QLabel(w);
    label->setText(QString("标签页") + QString::number(cnt + 1));

    ui->tabWidget->setCurrentIndex(cnt);

}

void Widget::on_pushButton_del_clicked()
{
    int index = ui->tabWidget->currentIndex();
    ui->tabWidget->removeTab(index);
}
  1. 执行程序


 

3.6. 布局管理器

之前使⽤Qt在界⾯上创建的控件,都是通过"绝对定位"的⽅式来设定的.也就是每个控件所在的位置,都需要计算坐标,最终通过setGeometry 或者move ⽅式摆放过去.这种设定⽅式其实并不⽅便.尤其是界⾯如果内容⽐较多,不好计算.⽽且⼀个窗⼝⼤⼩往往是可以调整的,按照绝对定位的⽅式,也⽆法⾃适应窗⼝⼤⼩.因此Qt引⼊"布局管理器"(Layout)机制,来解决上述问题.

当然,布局管理器并⾮Qt独有.其他的GUI开发框架,像Android,前端等也有类似的机制.

3.6.1. QVBoxLayout(垂直布局)

使⽤ QVBoxLayout 表⽰垂直的布局管理器.V是 vertical 的缩写.
常用属性

属性

说明

layoutLeftMargin

左侧边距

layoutRightMargin

右侧边距

layoutTopMargin

上⽅边距

layoutBottomMargin

下⽅边距

layoutSpacing

相邻元素之间的间距

Layout只是⽤于界⾯布局,并没有提供信号

3.6.1.1. 代码示例1:使用QVBoxLayout管理多个控件
  1. 编写代码,创建布局管理器和三个按钮,并且把按钮添加到布局管理器中。

• 使⽤ addWidget 把控件添加到布局管理器中.
• 使⽤ setLayout 设置该布局管理器到widget中.

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");

    // 创建布局管理器,并把按钮添加进去,如果创建的时候指定父元素为this,则后面不需要setLayout方法了
    QVBoxLayout* layout = new QVBoxLayout();
    layout->addWidget(btn1);
    layout->addWidget(btn2);
    layout->addWidget(btn3);

    // 把布局管理器设置到widget中
    this->setLayout(layout);
}

3.6.2. QHBoxLayout(水平布局)

使⽤ QHBoxLayout 表⽰垂直的布局管理器.H是 horizontal 的缩写.
核⼼属性(和 QVBoxLayout 属性是⼀致的)

属性

说明

layoutLeftMargin

左侧边距

layoutRightMargin

右侧边距

layoutTopMargin

上⽅边距

layoutBottomMargin

下⽅边距

layoutSpacing

相邻元素之间的间距

3.6.2.1. 代码示例1:使用QHBoxLayout管理控件
  1. 使用代码创建三个按钮,并将按钮加入到布局管理器当中
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");

    // 创建布局管理器,并把按钮添加进去,如果创建的时候指定父元素为this,则后面不需要setLayout方法了
    QHBoxLayout* layout = new QHBoxLayout();
    layout->addWidget(btn1);
    layout->addWidget(btn2);
    layout->addWidget(btn3);

    this->setLayout(layout);
}
  1. 执行代码

3.6.2.2. 代码示例2:嵌套布局
  1. 创建三个按钮,将其中两个按钮水平布局,再将整体竖直布局
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    QPushButton* btn4 = new QPushButton("按钮4");

    // 创建布局管理器,并把按钮添加进去,如果创建的时候指定父元素为this,则后面不需要setLayout方法了
    QHBoxLayout* layout = new QHBoxLayout();
    layout->addWidget(btn1);
    layout->addWidget(btn2);



    QVBoxLayout* q = new QVBoxLayout();
    q->addWidget(btn3);
    q->addWidget(btn4);
    q->addLayout(layout);

    this->setLayout(q);
}

3.6.3. QGridLayout(网格布局)

Qt中还提供了 QGridLayout ⽤来实现⽹格布局的效果.可以达到M*N的这种⽹格的效果.
核⼼属性
整体和 QVBoxLayout 以及 QHBoxLayout 相似.但是设置spacing的时候是按照垂直⽔平两个⽅向来设置的.

属性

说明

layoutLeftMargin

左侧边距

layoutRightMargin

右侧边距

layoutTopMargin

上⽅边距

layoutBottomMargin

下⽅边距

layoutHorizontalSpacing

相邻元素之间⽔平⽅向的间距

layoutVerticalSpacing

相邻元素之间垂直⽅向的间距

layoutRowStretch

⾏⽅向的拉伸系数

layoutColumnStretch

列⽅向的拉伸系数

3.6.3.1. 代码示例1:使用QGridLayout管理元素
  1. 代码中创建QGridLayout和四个按钮

使用addWidget添加控件到布局管理器中,但是添加的同时会指定两个坐标,表示放在第几行,第几列

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    QPushButton* btn4 = new QPushButton("按钮4");

    // 创建网格布局管理器,并且添加元素
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(btn1, 0, 0);
    layout->addWidget(btn2, 0, 1);
    layout->addWidget(btn3, 1, 0);
    layout->addWidget(btn4, 1, 1);

    // 设置layout到窗口中
    this->setLayout(layout);
}

3.6.4. 表单布局

除了上述的布局管理器之外,Qt还提供了 QFormLayout ,属于是 QGridLayout 的特殊情况,专⻔⽤于实现两列表单的布局.
这种表单布局多⽤于让⽤⼾填写信息的场景.左侧列为提⽰,右侧列为输⼊框.
 

3.6.4.1. 代码示例1:使用QFormLayout创建表单
  1. 创建QFormaLayout,以及三个label和三个lineEdit,使用addRow方法添加一行,每行包含两个控件,第一个控件固定式QLabel/文本,第二个控件则可以是任意控件,如果把第一个参数填写为NULL,则什么都不显示
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QFormLayout* layout = new QFormLayout();
    this->setLayout(layout);

    QLabel* l1 = new QLabel("name");
    QLabel* l2 = new QLabel("age");
    QLabel* l3 = new QLabel("tel");

    QLineEdit* e1 = new QLineEdit();
    QLineEdit* e2 = new QLineEdit();
    QLineEdit* e3 = new QLineEdit();

    // 创建一个提交按钮
    QPushButton* btn = new QPushButton("提交");

    // 把上述元素移动到layout当中
    layout->addRow(l1, e1);
    layout->addRow(l2, e2);
    layout->addRow(l3, e3);
    layout->addRow(nullptr, btn);
}

3.6.5. Spacer(添加一段空白)

使⽤布局管理器的时候,可能需要在控件之间,添加⼀段空⽩.就可以使⽤ QSpacerItem 来表⽰.
核⼼属性

属性

说明

width

宽度

height

⾼度

hData

⽔平⽅向的sizePolicy
• QSizePolicy::Ignored :忽略控件的尺⼨,不对布局产⽣影响。
• QSizePolicy::Minimum :控件的最⼩尺⼨为固定值,布局时不会超过该值。
• QSizePolicy::Maximum :控件的最⼤尺⼨为固定值,布局时不会⼩于该值。
• QSizePolicy::Preferred :控件的理想尺⼨为固定值,布局时会尽量接近该
值。
• QSizePolicy::Expanding :控件的尺⼨可以根据空间调整,尽可能占据更多空
间。
• QSizePolicy::Shrinking :控件的尺⼨可以根据空间调整,尽可能缩⼩以适应
空间。

vData

垂直⽅向的sizePolicy
选项同上.

上述属性在构造函数设置即可.

3.6.5.1. 代码示例1:创建一组左右排列的按钮
  1. 在界面上创建一个QVBoxLayout,并添加两个按钮
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QHBoxLayout* layout = new QHBoxLayout();
    this->setLayout(layout);

    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");

    layout->addWidget(btn1);
    layout->addWidget(btn2);
}

运行代码后发现,两个按钮离得很近

  1. 在两个按钮中间添加一个spacer

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QHBoxLayout* layout = new QHBoxLayout();
    this->setLayout(layout);



    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");

    QSpacerItem* spacer = new QSpacerItem(200, 20);

    layout->addWidget(btn1);
    layout->addSpacerItem(spacer);
    layout->addWidget(btn2);


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1570789.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于单片机的有害气体检查系统设计

**单片机设计介绍&#xff0c;基于单片机的有害气体检查系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的有害气体检查系统设计旨在实现对环境中各种有害气体的实时监测与报警&#xff0c;保障人员健康和环境…

CMD 命令行进入到电脑硬盘的某个目录的几种方式

本文介绍几种 cmd 命令行进入到电脑硬盘的某个目录的几种方式。 1、在具体文件目录地址栏输入 cmd 回车 这是最快的、最牛的方式&#xff0c;没有之一。 比如&#xff1a;我想进入一个层级很深的文件目录&#xff0c;直接打开在那个目录&#xff0c;把地址栏信息删除清空&am…

记忆力考验游戏-第15届蓝桥第5次STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第178讲。 如果想持续关注Scratch蓝桥真题解读&#xff0c;可以点击《Scratch蓝桥杯历年真题》并订阅合集&#xff0c;…

nuitka和pyinstaller打包文件大小对比

最近看到一篇文章&#xff0c;介绍nuitka打包Python程序&#xff1a;比较PyInstaller和Nuitka 听说Nuitka打包文件会获得更小的文件体积&#xff0c;我准备测试一下。 1、用两种方式打包程序 写一个简单的wxPython程序&#xff1a; # demo.pyimport wxapp wx.App() frame…

使用pip install替代conda install将packet下载到anaconda虚拟环境

问题描述 使用conda install 下载 stable_baseline3出现问题 一番搜索下是Anaconda.org缺少源 解决方法 首先使用管理员权限打开 anaconda prompt 然后激活目标环境&#xff1a;conda activate env_name 接着使用&#xff1a;conda env list查看目标env的位置 如D:\anacon…

有关字符串算法

例题一 解法&#xff1a; 算法思路&#xff08;两两⽐较&#xff09;&#xff1a; 我们可以先找出前两个的最⻓公共前缀&#xff0c;然后拿这个最⻓公共前缀依次与后⾯的字符串⽐较&#xff0c;这样就可以找出所有字符串的最⻓公共前缀。 例题二 解法&#xff08;中⼼扩散&am…

Android Studio学习8——点击事件

在xml代码中绑定 在java代码中绑定 弹出一个toast 随机&#xff0c;数组

Linux: linux常见操作指令

目录 01.ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令&#xff08;重要&#xff09; 06.rmdir指令 && rm 指令&#xff08;重要&#xff09; 07.man指令&#xff08;重要&#xff09; 07.cp指令&#xff08;重要&#xff09; 08.mv指令&#…

stargan项目实战及源码解读

数据及代码链接见文末 ​​​​​​​论文解析&#xff1a;Star GAN论文解析-CSDN博客 1.测试模块效果与实验分析 测试数据需要准备两个文件夹src&#xff08;源&#xff09;和ref&#xff08;目标&#xff09;&#xff0c;这两个文件夹下的文件夹名称代表各个domain。 运行测…

【随笔】Git 高级篇 -- 撤销变更(十四)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

基于单片机便携式太阳能充电器系统设计

**单片机设计介绍&#xff0c;基于单片机便携式太阳能充电器系统设计 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机便携式太阳能充电器系统设计概要主要涉及利用单片机作为核心控制器件&#xff0c;结合太阳能充电技术和便携式…

java-网络编程socket-聊天室-先导

这边我会简单介绍一下聊天室的组成部分,和思路的引导 涉及知识点 java 中异常处理机制 和 io流和网络编程socket 简单回顾异常机制 Java中的异常机制是一种用于处理程序运行期间出现的错误或异常情况的机制。这种机制允许程序员定义在特定情况下可能发生的错误&#xff0c;并…

Revit 2025新功能一览~

Hello大家好&#xff01;我是九哥~ Revit2025已经更新&#xff0c;安装后&#xff0c;简单试了下&#xff0c;还是挺不错的&#xff0c;流畅度啊&#xff0c;新功能啊&#xff0c;看来还是有听取用户意见的&#xff0c;接下来就简单看看都有哪些新功能。 好了&#xff0c;今天的…

小红书自动化仿写发文机器人了解一下

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

CCIE-08-BGP-Listen

目录 实验条件网络拓朴实验目的 开始配置配置动态路由协议配置BGP检查邻居配置 实验条件 网络拓朴 实验目的 将R1配置成Listen状态&#xff0c;自动接收来自其它路由器的建邻居请求、建立邻居 开始配置 配置动态路由协议 这里用EIGRP来配置&#xff0c;保证网络的可达性&a…

2024年华为OD机试真题-推荐多样性-Java-OD统一考试(C卷)

题目描述&#xff1a; 推荐多样性需要从多个列表中选择元素&#xff0c;一次性要返回N屏数据&#xff08;窗口数量&#xff09;&#xff0c;每屏展示K个元素&#xff08;窗口大小&#xff09;&#xff0c;选择策略&#xff1a; 1. 各个列表元素需要做穿插处理&#xff0c;即先从…

ES11 学习

文章目录 1. Promise.allSettled2. Module 新增2.1 ! 动态导入 import()2.2 import.meta2.3 export * as obj from module 3. 字符串 matchAll()4. BigInt实际开发相关使用 5. globalThis6. 空值合并运算符7. 可选链操作符 1. Promise.allSettled Promise.allSettled() 返回一个…

应急响应实战笔记05Linux实战篇(2)

第2篇&#xff1a;捕捉短连接 0x00 前言 ​ 短连接&#xff08;short connnection&#xff09;是相对于长连接而言的概念&#xff0c;指的是在数据传送过程中&#xff0c;只在需要发送数据时&#xff0c;才去建立一个连接&#xff0c;数据发送完成后&#xff0c;则断开此连接…

Azure service tag 导致的Exchange online 无法发送邮件的问题

最近碰到一个比较有趣的客户问题。 这个客户一直在使用Exchange online 与自己在Azure Vnet 里面的exchange server交换邮件。 客户的网络架构如下图所示。 客户说之前从exchange online往外发邮件一直是好的,但是最近两周开始只有百分之3左右的邮件可以发出去,其他的都pen…

C语言中的结构体:高级特性与扩展应用

前言 结构体在C语言中的应用不仅限于基本的定义和使用&#xff0c;还包含一些高级特性和扩展应用&#xff0c;这些特性和应用使得结构体在编程中发挥着更加重要的作用。 一、位字段&#xff08;Bit-fields&#xff09; 在结构体中&#xff0c;我们可以使用位字段来定义成员…