news 2026/9/12 17:48:15

常用控件的介绍(下)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
常用控件的介绍(下)

0.引言

现在开始介绍的各种Qt中的控件,都是继承自QWidget,所以QWidget的属性在接下来的控件中都是可以使用的。也就是刚刚QWidget中涉及到的各种属性/函数/使用方法,针对接下来要介绍的Qt中的各种控件都是有效的,下面来学习Qt中提供的各种控件。

1.PushButton

使用QPushButton表示一个按钮,QPushButton继承自QAbstractButton类,这个类是个抽象类,是其它按钮的父类(抽象类包含了纯虚函数,无法创建出实例对象。需要创建子类,重写上述的纯虚函数,才能够创建出子类的实例)。这有个图,描述了按钮类的继承体系:

QAbstractButton里提供了一些这样的属性:

接下来通过代码感受一下这些属性的效果,先来给按钮加一个图标。先把图片导入到项目中,使用qrc的方式管理(后续编写代码,如果用到一些图片等外部资源,都会优先考虑qrc,除非资源太大):

添加好后就可以在代码中访问到resource.qrc里面的文件了。创建一个按钮:

然后进行完善并运行:

还可以把图标调整大一些:

接下来给按钮添加快捷键,前面写过一个例子,通过4个按钮控制target按钮的移动。之前的移动是通过鼠标点击按钮来实现的,此处就可以引入快捷键,通过快捷键来操作。下面写一下,此处的按钮通过图片来表示:

此处把图片导入项目的时候,由于图片多了,不想再继续放到项目根目录下了。就创建了image目录,把图片放到image目录中,此时就意味着后续访问到这些图片,就需要再路径中带上image这一级目录名字。有了图片资源后,下面编辑ui创建界面(属性中改好名字):

右上边可以看到,Qt程序运行过程中,对象树的模样,更直观的看到对象树结构以及每个对象的objectName。界面准备完毕了,下面进一步的编写构造函数,完成初始化操作:

下面实现方向键的槽函数:

运行可以看到基本功能都以及没有问题了。下面设置快捷键,在Widget的构造函数中完成,这样程序一启动快捷键就有效:

它的参数是QKeySequence对象。key表示按键,sequence表示序列,说明按下的快捷键不一定是单个按键,也可能是组合键:

运行发现可以达到基本的要求。通过按键的名字来设置,虽然简单,但是容易写错。这里还可以通过按键的枚举来设置按键快捷键:

这样可以确保拼写不会出错。也可以用这种方式写组合键,比如:

若是第一种方式则这样写:

再说说连发功能,现在的程序,键盘快捷键默认可以连发,但鼠标点击按钮不可以,我们需要设置一下autoReapeat(true):

此时就可以了。

2.Radio Button

QRadioButton是单选按钮,可以让我们在多个选项中选择一个。它也是继承自QAbstractButton,一些属性和QRadioButton直接相关:

下面通过代码来演示,先创建一些按钮(顺便修改objectname,来完成性别选择):

接下来再来一个label用来显示用户的结果:

此时界面创建好了,接下来给三个按钮添加槽函数:

测试也发现,上述的选择过程有排他的效果,选了一个就会自动取消其它的选中状态。前面代码中看到程序一启动是没有选中任何选项的,我们也可以让程序一启动有一个默认的选项:

此时就会有默认选项了。比如想禁用其他选项:

现在虽然无法选中,但点击事件可以响应,所以checkable只是能够让按钮不被选中,仍然可以响应点击事件,所以这样:

此时这样的按钮彻底变成了灰色,点击后也没有用。

前面在转到槽时,看到QAbstractButton里提供了很多信号:

那这些信号都是干什么的呢?clicked表示点击,pressed表示按下,released表示抬起。通过代码感受一下:

创建了一些按钮,然后设置不同的槽函数(1关联clicked(bool) 2关联pressed 3关联released 4关联toggled):

下面运行程序来看看:

其余的都好理解,说说4,当点击4时,checked从flase状态变为了true,所以会触发toggled信号。当继续点击4就没有反应了,因为没有涉及到切换,当再次点1看到1这里的clicked确实触发了,但是4的toggled也触发了,因为在排他机制下4从true变成了false。

接下来结合上述来写一个复杂一些的例子,基于QRadioButton实现一个简单的模拟点餐的功能。先设计一下界面:

RadioButton默认是排他的,一旦界面上需要存在“多组”单旋按钮的时候,希望组和组之间不要有影响。Qt中引入了QButtonGroup类,可以针对单旋按钮进行分组,这样可以确保排他机制是按照每个组来展开的。下面完成一下:

此时不同组里面就不存在排他了。

3.QCheckBox的使用

QCheckBox表示复选按钮,可以在多个选项中选中任意多个选项。这个按钮的属性也是继承自QAbstractButton,主要是checkable和checked。下面来通过代码演示一下,先创建一下界面:

下面来添加槽函数:

4.QLabel

显示类控件,就是用来在界面上显示一段内容的。其中最主要用到的控件就是Label标签,这是Label或QLabel类的一些重要的属性:

下面通过代码来演示一下,先来演示一下textFormat起到的效果:

继续编写代码:

虽然给label设置了不同的文本格式,直接运行程序看起来好像没有什么区别,因为富文本和markdown里面1并没有包含真正的对应的符号。下面加些东西让它看起来有一些变化:

这些加的符号如果加在纯文本中,只会被当作是纯文本的一部分。

下面来用QLabel显示图片:

把图片资源用qrc机制管理好:

然后编辑代码,先把QLabel设置成和窗口一样大,并且把这个QLabel左上角设置到窗口左上角,让整个QLabel铺满整个窗口。窗口的大小可以在ui文件中选中窗口后看到:

可以写死,也可以不用写死:

看到图片并没有真的把整个界面都铺满,因为窗口是800*600,QLabel也是一样了,图片就不一定了。我们可以使用scaledContents来自动拉伸:

现在填充满了,但是我拖动窗口又不满了:

在上面代码中,我们在构造函数进行了setGeometry尺寸设置,这个设置相当于是”一次性的“,一旦程序运行起来后,QLabel的尺寸就固定下来了。窗口发生改变,此时QLabel是不会变化的。那怎样让QLabel随着窗口大小时时发生改变呢?这里先提前说个知识点叫事件。Qt中表示用户的操作,有两类概念,一个是信号,另一个是事件。当用户拖拽修改窗口大小的时候,就会触发resize事件(resizeEvent)。像resize这样的事件,是连续变化的,把窗口尺寸从A拖拽到B这个过程,会触发一系列的resizeEvent。此时就可以借助resizeEvent来完成上述的功能,可以让Widget窗口类,重写父类(QWidget)的resizeEvent虚函数。在鼠标拖拽窗口尺寸的过程中,这个函数就会被反复的调用执行。每次触发一个resizeEvent事件,都会调用一次对应的虚函数。由于此处进行了重写,调用父类的虚函数就会实际调用到子类的对应的函数。下面来实现:

我们可以打印来看看:

发现拖拽的过程中,发生了一系列的打印。在实际编程中,指定回调函数其实有很多种写法:1.设置函数指针。2.设置仿函数(函数对象)。3.设置lambda。4.通过重写父类虚函数(框架种拿着父类的指针调用这个函数,如果你创建了子类重写了这个函数,此时在多态机制下,实际执行的就是子类的函数了)。5.Qt的信号槽。继续来完善代码:

此时label尺寸始终和窗口大小是一致的。

接下来看QLabel的文本对齐,自动换行,缩进,边距相关的属性。先在界面上创建一些label出来:

在QtCreator右侧属性编辑区,能够看到类之间的继承关系。QLabel继承自QFrame,QFrame继承自QWidget。QFrame中有个frameShape属性,通过修改它可以给label加边框:

接下来针对这些label来设置它不同的属性:

下面演示一下QLabel伙伴,可以把QLabel和一个像单选框、复选框这样的控件绑定为一个伙伴关系,此时可以通过QLabel触发单选框或复选框等选择操作。下面先ui中编辑:

然后用代码把它们关联起来:

此时我按ALT+B对应的选项就可以被选中。Qt中QLabel中写的文本是可以指定”快捷键,此处快捷键的规则功能上要比QPushButton弱很多。是在文本中使用&跟上一个字符来表示快捷键,比如&A=>通过键盘上的atl+a来触发这个快捷键。绑定了伙伴关系后,通过快捷键就可以选中对应的单选按钮/复选按钮。

5.QLCDNumber

QLCDNumer是一个专门用来显示数字的控件,类似于 "老式计算器" 的效果。这是它的一些核心属性:

下面通过代码来感受一下,我们写一个倒计时,使用QLCDNumber显示一个初始的数值,比如10,每隔1秒钟数字就-1,一直到0就停止了。打开ui文件拖拽LCDNumber:

接下来完善代码:

此处的关键点是要实现“每秒钟-1”这个效果,怎样去实现这样的效果呢?它所体现的问题是周期性的执行某个逻辑。这种周期性执行某个问题我们往往会封装成一个组件供我们使用,这类组件我们称为定时器。C++标准库中没有定时器的实现,Boost里面提供了对应的功能。Qt中也封装了对应的计时器,它结合了信号槽的机制。Qt中提供了QTimer类,通过这个类创建出来的对象,就会产生一个timeout这样的信号,可以通过start方法来开启定时器,并且参数中设定触发timeout信号的周期。然后结合connect,把这个timeout信号绑定到需要的槽函数中,就可以执行逻辑,修改LCDNumber中的数字了。下面实现:

此时运行程序就可以看到计时器正常工作了。

此时可能会有疑惑,这个代码不用QTimer能不能达成类似的效果呢,比如构造函数里弄一个循环?下面来试一试,先创建ui文件:

接下来完善代码:

以前c语言中用过Sleep,这个Sleep是Windows的api,需要包含“Windows.h”头文件才能使用的。这个东西只能在vs中使用,qt用mingw gcc windows版本的编辑器,无法使用Windows.h。在c++11标准库中引入了sleep操作,叫做sleep_for,我们来使用:

我们运行后发现程序一直没有出来,等了一会程序窗口出来了,但是显示的是0:

这里是Widget的构造函数,需要把Widget构造完毕,然后才能show执行后续的显示操作:

因此达不到预期的倒计时的效果。那可不可以在构造函数中,另外创建一个线程,在新的线程中执行上述循环+更新操作?我们试一下:

运行发现提示我们进程终止了。Qt里,界面有一个专门的线程去负责维护更新的(主线程)。对于GUI来说,内部包含了很多的隐藏状态,Qt为了保证修改界面的过程中,线程安全是不会受到影响的,Qt禁止了其它线程直接修改界面,形如上面30行就是在修改界面。因此Qt为了确保线程安全,直接要求所有的对界面的修改操作,必须在主线程中完成。对于Qt的槽函数来说,默认情况下,槽函数都是由主线程调用的,在槽函数中修改界面是没有任何问题的。在main函数后面有exec,exec就会使主线程进入“事件循环”,exec就会一直循环下去,每执行一次循环,都会有一些固定的事情要操作,比如执行槽函数。

6.QProgressBar

它表示一个进度条,这里有进度条的一些相关的属性:

接下来通过代码感受一下,创建一个进度条,让这个进度条的进度跟随事时间增长(可以假设,每隔100ms,让进度条数值+1)。先来编辑ui文件:

然后切回代码:

运行程序就可以看到进度条在增长了。

这有个细节,上述代码中,我们把QTimer头文件放在了widget.h中:

在前面QLCDNumber中,头文件包含是放在.cpp中的。我们现在放过来,程序还是可以正常运行的:

此时可以看到一个问题:

我们虽然在widget.h中用到了QTimer,但是确没在.h中包含<QTimer>头文件。那为啥这个代码编译不会出错?为啥此处的QTimer就不会提示‘找不到定义’之类的错误?上述问题其实是通过Qt内部提供的一个特殊技巧来实现的,在Qt中有一个专门的头文件,这个头文件中包含了Qt中所有类的“前置声明”:

这个头文件,一般不会直接接触到,但是包含其它的Qt的头文件,都会间接的包含到这个头文件。因此前面没有报错,是由于在WIdget类的前面已经提供了QTimer类的声明的话,此时就可以在Widget中使用QTimer的指针/引用类型的成员。这个是C++中的特殊技巧,在Qt中被使用到了。后续如果真正使用QTimer(包括创建实例,使用里面的成员),仍然需要包含QTimer的头文件(包含了QTimer的详细的类的定义)。

上面的代码中进度条是绿色的,那能不能改成是一个红色的进度条。重新创建编辑ui:

QProgressBar::chunk是个选择器,就是咱们设置的样式,到底要针对哪个控件。chunk就是这个部分:

就是把背景色改为了红色。变红色后发现:

数字跑到左上角了(可能是Qt的bug)。虽然不能放在最初的位置了,但是可以自己调整一下:

7.QCalendarWidget

它表示一个日历,这是一些相关的属性:

这是它提供的一些信号:

下面通过一个简单的例子,来用一下日历的使用方式。在ui中编辑:

我们用日历里提供的信号:

通过这个信号表示选中的内容是哪一个。继续完善:

此时点击哪一个日期,label里就会显示哪一个日期。

8.QLineEdit

下面开始介绍一些输入类的控件,和前面显示类的控件不同,显示类的控件只是负责显示,输入类控件既能显示又能让用户去输入一些内容。使用最广泛的输入类控件是QLIneEdit,表示单行输入框,可以输入一段文本,不能换行。这是它的一些核心属性:

这个text属性不仅仅可以通过代码来设置,用户在输入框中进行编辑,也会影响到text值的变化。这还有一些关于输入框的信号:

下面通过代码来感受一下,让用户输入我们指定的个人信息,然后通过提交按钮把上述内容给统一获取到。先来编辑ui文件:

下面切回代码:

下面测试一下:

上述例子中我们使用InputMask属性来验证用户输入的是否是一个正确的电话号码,但是inputMask功能比较有限,只能进行简单的验证。若想进行更复杂的验证,就需要使用”正则表达式“。它是一个计算机中的通用概念,和具体的编程语言无关。正则表达式,本质上就是一个带有特殊字符的字符串,特殊字符用来表示另一个字符串的特征,此时就可以借助正则表达式来描述出一些具有一定特点的字符串,基于这些特点就可以完成字符串的匹配。这是正则表达式的语法:

正则表达式语法 | Microsoft Learnhttps://learn.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2008/ae5bf541(v=vs.90)?redirectedfrom=MSDN这是正则表达式测试的在线工具:

正则表达式语法测试工具 - 在线工具 (buyaocha.com)https://regextester.buyaocha.com/用到的时候查就可以了。接下来通过正则表达式来对输入框输入手机号验证一下,先编辑ui:

此处的规则是,输入框要检查输入的内容是否是合法的手机号码,如果是则按钮设为可用状态,如果不是则设为禁用状态。下面编辑代码:

这是一个简单的验证手机号码的正则表达式。^表示以xxx开头,^1意思就是以1开头;\d表示数字,为了在c++字符串中使用需要写作\\d;{10}表示前面的内容重复出现10次,\d数字要重复出现10次;$表示结尾。继续写:

现在只是注册了一个验证器,具体验证器怎么使用,还需要写其它代码来完成。验证输入框的内容是否合法,只要输入框的内容发生改变了,验证操作就应该被执行。继续写:

下面验证一下:

下面再基于LineEdit写一个例子,来完成验证两次输入的密码是否一致。先来编辑ui文件:

下面来完善代码:

然后使用textEdited信号,来触发对于两个输入框内容的判定:

上述代码完成了响应的要求,但是形参我们没有用到,所以会有警告。如果想消除警告可以这样:

这个写法是类型转换,这个写法对于代码的实际逻辑是没有任何影响的,同时可以”骗过“编译器,警告就没有了。

再实现一个功能,针对密码,可以切换”显示密码“状态。先来编辑ui文件:

下面来编辑代码:

下面运行一下:

9.QTextEdit

QTextEdit表示多行输入框,在Qt中表示多行输入框有QTextEdit和QPlainTextEdit。QPlainTextEdit只能表示纯文本,QTextEdit不仅能表示纯文本,还可以表示html和markdown。继续说QTextEdit,这是它所包含的一些核心属性:

这有一些相关的信号:

下面通过代码来感受一下,我们在输入框中输入内容,然后显示到label上面去。先编辑一下ui文件:

下面来写代码(转textChanged信号):

下面再写例子,显示QTextEdit这几个信号(ui文件中放一个输入框)。下面演示:

10.QComboBox

它表示下拉框,这是它的一些核心属性:

这是一些核心方法:

还有一些信号:

下面通过代码来感受一下,模拟一下麦当劳点餐。先编辑一下ui文件:

下面编辑代码:

此时就有条目了。现在编辑一下提交按钮:

以上就是下拉框基本的使用方式。上面用代码的方式编辑的下拉框中的内容,也可以使用图形化的方式来进行编辑:

再写一个例子,下拉框里的内容,很多时候不是代码中写死的,而是通过文件/网络加载数据得到的。下面演示一下通过文件加载,先编辑一下ui文件:

然后选中从文件中加载老婆的信息。创建一个文件并填好一些信息:

继续编辑代码:

此时就有了一个动态改变的效果。

11.QSpinBox

它表示微调框,大概是这样的输入框:

输入框可以输入整数或小数,右边有按钮,可以通过按钮对里面的数值进行微调。这是QSpinBox的一些相关的属性:

还有一些相关的信号:

下面通过代码来感受一下,还是以点餐为例,现在不光可以选则食物,还可以通过微调框来选择具体的数量。先编辑ui文件:

下面编写代码:

现在细节是,初始情况下微调框是0在这个场景下不合适,太多也不科学,我们再改进一下:

12.QDateTimeEdit

这些控件是基于微调框弄出来的输入时间或日期的控件,使用QDateEdit作为日期微调框,使用QTimeEdit作为时间的微调框,使用QDateTime作为时间日期的微调框。这几个控件用法非常相似,下面以QDateTimeEdit为例进行介绍。这是关于QDateTimeEdit的核心属性:

最后一个是使用的时间规范。这有一些核心信号:

下面通过代码感受一下,写一个时间计算器,计算两个时间中间的间隔是多少天/多少小时。先来编辑ui文件:

下面来编写代码:

上面的代码其实还有些小问题:

发现此时的结果是1天07小时,1号17点到2号的0点中间是隔了7个小时,不是1天07小时。我们计算天数用的daysTo函数,文档中查有两个,当前我们用的是第二个:

点进去看看描述:

说明计算的是之间有多少午夜。因此这样改进一下:

如果当前得到的小时数不足24,由于次数是整数除法,就会舍弃掉小数点后的内容。下面再次运行一下:

13.QDial

它表示一个旋钮,这是它的一些基本的核心属性:

这是它的相关信号:

下面通过代码来感受一下,先编辑一下ui界面:

我们要完成通过旋钮来控制窗口的不透明度(opacity)。我们先来一些设置:

下面来编写(用valueChanged信号):

那能否借助这个旋钮实现调整系统声音的功能呢?可以,但是没那么容易。调整系统声音是Windows系统的api,Qt没有封装这个api,此时就非常麻烦(系统原生的api使用起来也很麻烦)。此时就需要通过vs写一个动态库,把系统的原生api封装一下,再让Qt的程序来调用动态库。

14.QSlider

这个控件表示滑动条,QSlider和QDial都是继承自QAbstractSlider,因此用法上基本相同。这是它的相关属性:

这是它的核心信号:

下面通过代码演示一下,我们在窗口上放两个滑动条,一个是水平方向,一个垂直。滑动这两个滑动条,就可以调整窗口的大小。先编辑一下ui文件(往右变大,往下变大):

下面编写代码:

接下来给两个滑动条设置槽函数:

接下来再来写一个例子,写一个自定义快捷键,通过快捷键来操作滑动条。滑动条本身可以通过方向键和pageUp和pageDown操作,但是咱们也可以自定义。下面编辑ui文件:

下面编写代码:

此时就可以用我们的快捷键来增加和减小数值了。

15.多元素控件介绍

多元素意思是控价里面包含了很多的元素,元素可能指的是字符串,也可能是更加复杂的字符串等。这有一些具体的多元素控件:

前两个表示列表这样的结构,中间两个表示表格这样的结构,后面两个表示树形结构。那上面xxWidget和xxView是什么区别呢?概括来说,xxView是更底层的实现,xxWidget是基于xxView封装而来的。这样理解:

16.QListWidget

它表示一个能够纵向显示的列表,这是它所涉及到的一些属性:

这是它的一些核心方法:

说说第一个,列表中的每个元素/每一项就称为是一个item,更具体的说通过QListWidgetItem类表示的。再说说第五个,此处的row参数就表示插入完毕之后新的元素在第几行,把新元素插入到第几行之前。这还涉及到一些关键的信号:

下面通过代码来感受一下,可以输入框输入内容新增进去,也可以选中条目删除。先编辑一下ui文件:

下面编写代码:

先给列表添加一些初始元素。这是另一种添加方式:

也可以通过图形化的方式来添加,选中listWidget右键点编辑项目:

如果这里初始内容是固定的,此时通过哪种方式来初始化都可以;如果这里的内容是不固定的,要通过读取文件/读取网络来构造数据,就需要通过代码的方式来添加了。切回代码方式继续:

此时这样一个功能就完成了。还可以再加一些功能:

17.QTableWidget

它表示一个表格控件,一个表格中包含若干行,每一行又包含若干列。这是一些相关的核心方法:

这是一些核心信号:

表示每一个单元格可以用QTableWidgetItem,这是它的一些方法:

下面通过代码来感受一下,先编辑ui文件:

下面编写代码,图像化界面初始化:

运行先看看:

如果当前表格中的数据是固定的,完全就可以通过图形化的方式来进行编辑,但实际开发中很多时候数据是从文件/网络中来的,此时通过图形化编辑就不合适了。下面切回代码继续:

此时已经有了数据。下面完善一下按钮:

18.QTreeWidget

它表示一个树形控件,里面的每个元素,都是一个QTreeWidgetItem,每个QTreeWidgetItem可以包含多个文本和图标, 每个文本/图标为一个列。这是它所提供的相关的方法:

QTreeWidget控件虽然是树形结构,但是这个树形结构没有体现出根节点,它是从根结点的下一层子节点开始计算的:

这里的树画橘色框那里表示的是顶层结点。针对顶层结点来说,这里也是一个类似于“List”这样的结构。这是关于QTreeWidgetItem核心属性:

这是QTreeWidgetItem的核心方法:

通过上述知道顶层结点的相关操作都是在QTreeWidget这个类上面的,更往后的子节点都是借助QTreeWidgetItem提供的方法来操作的。

下面通过代码感受一下,先编辑一下ui界面:

可以通过图形化界面初始化数据:

最上面的1相当于树根结点,这就是通过界面的方式来获取。下面通过代码重新来操作:

此时添加好了顶层结点。继续完善:

初始化好了后,下面实现一下按钮的相关功能:

上述的几个控件相关的操作,数据都是在内存中保存的,无论界面上做任何操作,重新运行程序,之前的数据就都没有了。如果要想让数据能够重新启动也不丢失,就需要编写更多的代码把内存存储的数据获取到,写入到文件中,并且在下次运行的时候从文件加载数据。

19.QGroupBox

接下来介绍的控件是容器类控件,容器类控件指的是控件里面可以容纳其它的一些控件。多元素控件,包含的内容是一个一个的自定义好的“item”对象。容器类控件,包含的内容是前面已经学过的各种控件,比如QPushButton、QLineEdit、QLabel等。容器类控件这里主要介绍两个,一个是QGroupBox,表示分组框;还有一个是QTableWidget,表示标签页。

先来介绍QGroupBox,它大概是这个样子:

可以把其它的各种控件放到GroupBox种,这些内部的控件的父元素就不是this了,而是这个GroupBox。它存在的意义是,为了让界面看起来更好看一些。当一个界面比较复杂的时候,包含了很多控件的时候,分组框就可以把具有关联关系的控件组织到一起。这是它的核心属性:

下面通过代码演示一下,写一下麦当劳点餐,先编辑一下ui:

下面运行一下:

可以看到通过分组框把这里的控件进行了分组,可以让界面看起来更加清晰有条理。再看看属性:

看到勾选后只剩上面一根线了。

20.QTableWidget

它可以起到一个带有标签页的效果,然后可以在标签页里放一些其它的widget。先通过代码看一下标签页大概是什么样子:

可以看到有标签页的效果,每一个标签页里面都是可以放一些具体的控件的。比如:

可以放不同的label。如果想有更多的标签页或删除可以这样:

现在看看它所提供的属性:

这还有一些核心信号:

下面通过代码感受一下,创建一个程序,带有一个TableWidget作为标签页。提供两个按钮,分别创建新的标签页,关闭当前选中的标签页。当切换标签页的时候,也能感知到变化。先来编辑ui文件:

下面编写:

下面完善按钮:

再完善感知到标签页切换操作:

21.QVBoxLayout

下面介绍一下Qt中的布局管理器,之前把控件放到界面上,都是靠“手动”的方式来布局的。但是这种手动调整的方式是不科学的:1.手动布局的方式非常复杂,而且不精确。2.无法对窗口大小进行自适应。因此Qt引入了很多布局管理器:垂直布局,水平布局,网格布局,表单布局。

下面介绍一下垂直布局,Qt中使用QVBoxLayout表示垂直的布局管理器。这有一些核心属性:

下面通过代码感受一下:

但是,每个widget中只能设置一个布局管理器,往往可能不够,下面看看如何在widget中弄出多个布局管理器出来。先编辑ui文件:

看到存在两组Layout,每个Layout包含了多个按钮。但此时调整窗口大小,看到里面的内容并不会像前面那样随之发生变化。如果在代码中创建layout,其实是只创建了一个layout。如果在QtDesigner中创建layout,先创建了一个Widget,然后再这个新的Widget中添加了一个layout。刚才是先拖了layout过去,然后再往layout中托其它控件;也可以先托其它控件,后给这些控件套上layout:

这个按钮表示把选中的旋若干控件外头套上一个垂直布局的layout。

22.QHBoxLayout

这个表示水平布局管理器,这是它的相关属性:

下面通过代码演示一下:

现在界面上就把这三个按钮水平方向排列放到布局管理器中了。

布局管理器之间,也能进行嵌套。我们用一个垂直布局管理器把两个按钮添加进去,然后下面弄一个水平的布局管理器,把水平布局管理器添加到垂直布局管理器中,再往水平布局管理器里面添加两个按钮。下面实现:

23.QGridLayout

前面使用水平布局+垂直布局可以起到一种二维化布局的方式,但是全依赖这个东西写代码会比较的麻烦。于是这里说说网格布局,可以更方便的实现M*N这样的一个效果。这是它的一些属性:

下面看看网格布局最基本的使用情况:

这样完成了最基本的网格布局。这里是排列成了2*2的效果,也可以修改坐标起到更加灵活的布局效果:

这个写法就相当于水平布局了,此时这里的行数只要是一样的即可,不一定非是0。下面再改变一下代码:

这个写法相当于垂直布局了。再比如:

这种写法是每个按钮独占一行或一列。若把上述的3,3改为100,100,运行后发现是一样的。说明即使设置成100,也不会在中间搞出很大的空白空间。此处的行数和列数,只是用来决定空间之间的相对位置。

接下来介绍一下布局管理器中拉伸系数的问题:我们刚才创建的布局管理器,这里的控件尺寸都是均等的。当我们需要创建出尺寸不同的控件的时候,就可以通过拉伸系数来设置。拉伸系数就相当于,设置控件之间尺寸的比列。下面结合代码来演示一下:

此时按钮按照2行3列的方式排列好了。上述按钮看上去宽度都是一样的,接下来设置拉伸系数:

这个拉伸系数中有个特殊的取值0:

如果拉伸系数设为0,意思是不参与拉伸,此时按钮的宽度是固定值。此时调整窗口大小,可以看到第一列的窗口尺寸大小并没有改变。

接下来重新创建项目,看看垂直方向的拉伸该怎么设置:

现在把按钮按照3行2列的方式排列进去了。下面设置拉伸系数:

运行发现代码看上去没什么效果。上述代码,直接设置拉伸系数,发现是无效的。这里之所以没有拉伸,是因为SizePolicy起到的影响。这个是QWidget的属性,它有这些属性:

由于按钮垂直方向默认没有拉伸开(水平方向默认是拉伸的),因此垂直方向不会受到拉伸系数的影响了。要想让垂直方向的拉伸系数生效,就需要让按钮先能够拉伸展开:

看到垂直拉伸打开后,变化非常大比起之前。有了这个前提,现在再设置拉伸系数:

发现拉伸可以生效了,此时高度尺寸是1:1:2来展开的。

24.QFormLayout

下面介绍一下Qt中的表单布局,它本质上属于网格布局的一种特殊情况。下面结合代码来演示一下:

还可以添加按钮进去:

25.QSpacerItem

接下来介绍一下Qt中的Spacer,它是搭配布局管理器使用的工具,它表示一段空白。因为布局管理器里默认情况下控件和控件之间挨着比较紧,如果期望控件之间有一个比较明显的间隔,就可以使用这样1一个类。这是它的一些属性:

接下来通过代码演示一下使用情况,我们想让水平方向上有两个按钮,然后两个按钮不是仅仅挨在一起的,而是中间有空白:

现在是水平方向排列,但是按钮间非常近。下面来用空白:

ui中也是可以添加空白的:

它们都是SpaceItem。

26.总结

上述的每个控件,都是可扩展的。每个控件都是Qt内置的一个类,咱们在代码中都可以基于这个类,继承出你自定义的子类。在这个自定义的子类中,又可以添加很多的属性和方法,实现你自己的需求场景,还可以在子类中,把多个控件组合到一起。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 17:47:36

XPipe 界面语言切换完整指南:3 步搞定中文界面

XPipe 界面语言切换完整指南&#xff1a;3 步搞定中文界面 【免费下载链接】xpipe Access your entire server infrastructure from your local desktop 项目地址: https://gitcode.com/GitHub_Trending/xp/xpipe XPipe 是一款从本地桌面直接管理整台服务器集群的工具—…

作者头像 李华
网站建设 2026/9/12 17:47:34

AI创业者通识日报 | 2026年8月17日

AI创业者通识日报 | 2026年8月17日 今日头条 01 DeepSeek 提价今日生效——两年价格战正式终结&#xff0c;AI 进入"价值回归"时代 头条 行业拐点 北京时间 8 月 17 日 00:00&#xff0c;DeepSeek 全线引入 峰谷定价 正式生效。V4-Pro 输出价从 \$0.87 涨至高峰 …

作者头像 李华
网站建设 2026/9/12 17:47:29

GPT-5.3架构解析与多模态AI应用实践

1. GPT-5.3技术架构深度剖析 GPT-5.3作为OpenAI最新推出的多模态大模型&#xff0c;其架构设计体现了当前AI领域的最前沿思考。与上一代GPT-5.2相比&#xff0c;最显著的变化在于采用了混合专家系统(MoE)架构。具体来说&#xff0c;模型包含2048个专家子网络&#xff0c;每个输…

作者头像 李华
网站建设 2026/9/12 17:44:35

AI引擎驱动游戏出海:买量与本地化的自动化实践

这两年做游戏出海&#xff0c;最直观的感受是&#xff1a;买量费用一年比一年高&#xff0c;本地化却始终像一座绕不过去的山。我们上一款休闲产品在北美、东南亚和拉美三个区域跑了整整一年&#xff0c;买量消耗从年初的20美元左右一个安装&#xff0c;涨到年底接近40美元&…

作者头像 李华