QT之常用控件

一个图形化界面当然需要有各种各样的控件,QT也不例外,在QT designer中就有提供各种各样的控件,用以开发图形化界面。

而想使用好一个QT控件,就需要了解这些控件。

QWidget 

在QT中,所有控件都继承自 QWidget 类,如按钮、输入框、文本框之类的控件,都继承自该类。

换言之,该类包含所有控件通用的部分。

在QT desigener 中,我们每使用一个控件,都可以在右下角看到对应的 QWidget 属性。

这些核心属性我们可以在右下角的表中修改,也可以通过函数修改。 

接下来我们了解一些 QWidget 类的核心属性。

enabled属性

API 名称说明
isEnabled()获取控件的可用状态
setEnabled()设置控件是否可用,true表示可用,false表示禁用

 给一个按钮设置一个槽函数,将控件状态设置为不可用。

发现点击了一次后,按钮就不可用了。 

在 QT Designer 界面,我们能够看到一个控件其有两个父类——QObject 和 QWidget。

QObject 是 QWidget 的父类,它最主要的属性就是 objectName,在QT中,objectName是QT辨识对象的唯一标识,互相之间不可重复,在QT Designer 中可以通过objectName获取一个对象。

这是因为 designer 的 ui 文件本来是xml格式的,通过 .qmake 编译器将 xml 文件转换成 C++的 .h 头文件(build文件中),由此构成一个 ui_widget 类。这样每个控件的 objectName 就会变成 ui_widget 类的属性成员,因此 UI::Widget *ui 这个成员就能够通过 objectName 访问对应的控件对象了。 

geometry属性

这个属性包含四个属性的统称。

  • x 横坐标
  • y 纵坐标
  • width 宽度
  • height 高度

其中,x和y坐标是指一个控件左上角相对于该控件的父元素的左上角的距离。

比如我们设置一个按钮,其坐标应该是这样的。

其中,由于QT都是左手坐标系,因此使用的时候都需要从左上角开始计算。 

而我们可以通过API来设置属性。 

API说明
geometry获取控件的位置和尺寸,返回一个QRect对象,包含 x、y、height、width四个属性

setGeometry(QRect)

setGeometry(int x,int y,int width,int height)

设置属性有两种方式:直接通过 QRect 对象设置,或者直接通过传递 int 变量设置。

接着我们示例一下,首先是直接通过QRect变换按钮位置。 

 我们发现 x 确实修改了,但是按钮的长和宽都改变了,而如果不想修改按钮的长宽就需要采用其他方案。

 

 

发现确实是整个都移动了。 

frame的影响

QWidget 是一个窗口,包括标题栏、最小化、最大化、关闭按钮等,因此计算尺寸和坐标时有两种算法,包括 frame 的和不包括 frame 的。 

API说明
x()

获取横坐标

包括 window frame

y()

获取纵坐标

包括 window frame

pos()

返回 QPoint 对象,包括 x(),y(),setX(),setY()等方法

包括 window frame

frameSize()

返回QSize 对象,包括 width(),height().setWidth(),setHeight()等方法

包括window frame

freamGeometry()

返回QRect对象,这个包括 x,y,width,height 等属性和修改方法

包括windowframe

-—————————————以下函数不包括window frame—————
width()获取宽度
height()获取高度
size()获取QSize对象、包含 width(),height()以及setWidth(),setHeight() 方法
rect()获取QRect对象,包含 x,y,width,height属性以及设置函数
geometry()获取QRect,同上
setGeometry()设置 QRect。

说了这么多,frame是什么呢?实际上frame就是窗口的标题框的位置。

包含 frame 获取的坐标就是从标题框左上角开始计算,而不包含则是从下图的蓝色位置开始计算。

我们可以通过实验看一下framegeometry和 geometry 有什么区别。

一个是在构造函数时打印,一个是在按钮被按下去时打印。

 发现构造函数中两个打印的位置都一样,但是函数里的不同。

这是因为构造时 Widget 还未挂在对象树上,因此不具备 Window frame,不过后槽函数运行时就以及有frame了,因此不同。

WindowTitle属性

API说明
windowTitle()获取控件的窗口标题
setWindowTitle(const QString& title)设置控件的标题

通过这两个API可以设置标题。

WindowIcon属性

API说明
windowIcon()获取控件的窗口图标,返回QIcon对象
setWindowIcon(const QIcon& icon)设置窗口的图标

首先,我在d盘放入一张图片。

然后在代码中打开这张图片。

注意:这里打开文件的方式可以用 '\' 或者 '/',不过 \ 需要转义来使用, 即 \\ 的格式,因此使用的 / 。 

发现图标确实改变了。 

 同时任务栏的图标也改变了。

不过这种方式来修改图标的方式不是很好,因为这是绝对路径,无法保证所有用户都有一样的路径。

 而我们可以使用相对路径来修改图标。

  • 绝对路径:以盘符开头(windows)或 / 开头(linux) 的路径
  • 相对路径:以 . (标识当前路径) 或以 .. (表示上级路径),使用相对路径需要明确是当前工作目录

 一个QT程序,它的工作目录是变化的,如在QT Creator 运行的项目,其工作目录是项目的构建目录。

构建目录就是和QT项目并列的,用来存放临时文件和 exe 文件的目录,可以通过 Explorer 显示来找到QT项目,然后找到构建目录。

我们也可以在项目代码中直接获取工作目录。

 

如果我们将图片放在构建目录中,那么就能够保证每个用户都能成功换上图标。

但是!有个问题,因为构建目录很容易被删除,一旦清理项目,那么图片也就没了。

对于这种问题,QT 提供了 qrc 机制,来方便的管理项目依赖的静态资源。

 qrc机制:一种XML格式的配置文件,用XML记录硬盘上的文件和对应的资源名,应用程序通过资源名称访问这些资源。

通过将一些资源文件添加到项目中来管理,一般这些文件都位于qrc文件所在目录的同级目录或者子目录下

QT通过将这些文件转化了二进制数据写到 cpp 代码中,编译到 exe 文件中,使得资源与路径无关。

想要使用 qrc 来使资源和路径无关,就需要先创建一个qrc文件。

点击文件-> 新建文件或类->选择 QT 和 QT Resource File。这样就创建了一个 qrc 文件。

然后再通过给 qrc 文件添加前缀,然后添加文件即可。

 

添加后可以看到左边项目多出了一个文件。 

然后就可以直接设置图标了。

其中,使用 qrc 机制来获取资源有它自己的规则。

  • 使用 : 开头,表示从 qrc 中读取资源
  • /new/prefix1: 表示资源所在路径(不可有中文或者特殊符号)
  • test.jpg : 表示资源的名称

 qrc 机制实际上就是将 test.jpg 这个文件的每个字节记录下来,然后编译进exe文件中,这样文件就和资源路径不相关了。

优点:做到了资源路径和资源无关,不会丢失文件

缺点:当资源很大时,生成的exe文件也会很大,消耗的内存,编译的时间也会增加

WindowOpacity属性

API说明

WindowOpacity()

获取控件的不透明数值,返回 float 。

透明度在 0.0 -> 1.0 之间,0.0 表示完全透明,1.0表示完全不透明。

setWindowOpacity(float i)设置控件的不透明数值

通过这个函数我们能够获取 Window 的透明度,并且对透明度进行修改。

设置两个按钮。 

 然后设置槽函数分别会对MainWindow的透明度进行加和减。

 我们能够看到确实修改了窗口的透明度。

 

而 qDebug 的输出发现结果并不一定是精确的,有一定的精度缺失。 

 cursor属性

API说明
cursor()

获取当前 widget 的cursor属性,返回QCursor对象

当鼠标悬停在该 widget 上时,就会显示对应的形状

setCursor(const QCursor & cursor)设置该光标的形状,只有鼠标停留在widget上才有效
QGuiApplication::setOverrideCursor(cosnt QCursor& cursor)

设置全局的光标形状。

整个程序的光标都会改变,覆盖setCursor的内容

新添加一个按钮,该按钮可以修改 Cursor 属性。 

该控件的槽函数会给全局的控件都改变图标。 

 按下按钮后,发现所有控件的图标都变成了 WaitCursor,不管是窗口的还是其他按钮的。 

而 Cursor 属性有很多,通过 ctrl + 左键点击WaitCursor能够看到很多类型。

 而且这个图标我们也可以自定义。

发现图标确实被修改成自定义的图片了。 

font 属性

API说明
font()获取QWidget对象的信息,返回QFont对象
setFont(const QFont& font)设置该控件的字体信息

 一个字体也是具有各种各样的属性,如字体,粗体,斜线等...

API说明
family字体家族,有宋体,楷体,黑体等
pointSize字体大小
weight字体粗细,字体粗细程度从 [0,99]不等,数值越大越粗
bold是否加粗,true 表示是,false表示否
italic是否倾斜
underline是否有下划线
strikeOut是否带有删除线

对于字体我们可以在左下角的黄色框里面进行修改,或者通过代码修改。 

可以通过代码修改 

 

 toolTip属性

API说明
setToolTip(Qstring & str)

设置toolTip,

当鼠标悬停时就会有提示说明

setToolTipDuration(int)

设置toolTip提示的时间,单位是ms

时间到后自动消失

通过两个API可以设置按钮的提示信息以及提示信息存在的时间。

focusPolicy属性

通过设置某些控件能否通过焦点获取,如通过鼠标点击或者 Tab 键选中。

焦点:能否选中这个元素

比如星际中就需要选中单位然后才能命令单位进行任务。

输入框,复选框之类的都需要这个属性。 、

API说明
focusPolicy()

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

setFocusPolicy(Qt::FocusPolicy&)

设置widget的 focusPlicy

比如我们添加一个新控件--- lineEdit ,即单行输入框。

我们可以通过代码的形式来设置它的 FocusPolicy 属性。

 

而 FocusPolicy 一共有五个属性,分别对应不同的表现。

Qt::NoFocus :不接受焦点,即无法通过鼠标或者 Tab 键来选中控件

Qt::TabFocus : 只能通过 Tab 键选中,无法通过鼠标选中

Qt::ClickFocus : 只能通过鼠标选中,无法通过 Tab 键选中

Qt::StrongFocus :可以通过Tab 键和鼠标选中,也是控件的默认属性

Qt::WheelFocus : 类似 StrongFocus,不过还可以通过鼠标滚轮选中,比较少用。

当然我们也能在 Qt Designer 中修改这个值。 

 styleSheet属性

可以通过 CSS 设置 widget 的样式。

当然,CSS是网页前端的技术,并不是Qt的技术,不过 Qt 和 CSS 也有很多类似之处,因此也引入了 CSS 的技术,但是有没有全部引入,可以说引入了,又没完全引入。

比如这里有一个文本框,可以通过右键设置,然后编辑样式表,这样就可以输出 CSS 语言来控制文本框的样式了。

在这里使用的格式也是和 CSS 一样,用键值对设置样式。

键值之间用 : 隔开 ,不同的键值对之间通过 隔开。

不过 Qt 不能检测哪些不支持

而我们通过 CSS 修改的样式就是 styleSheet 属性。

当然,我们也能通过代码修改 styleSheet 属性。

API说明
setStyleSheet(QString& str)将 widget 的样式修改成 str 中的样式

比如我们设置两个按钮。 

它们的槽函数会分别修改窗口的背景颜色,字体颜色。

#fff :纯白色

#333 : 深色,不是纯黑

#000 : 纯黑色

能够看到确实进行了转化。 

在电脑中的所有颜色都是通过数字表示的,可以通过网站查看。在线调色板,调色板工具—在线工具 (sojson.com) 

按钮类控件

PushButton控件

QPushButton 就是一个按钮,它继承自 QAbstractButton 类。

QAbstractButton 是所有按钮的父类。 

我们也可以在 Qt Designer 中看到它的继承关系。

在 QAbstractButton中有些属性和 QPushButton 是高度相关的。

属性说明
text按钮文本
icon按钮图标
iconSize图标大小
shortCut按钮对应的快捷键
autoRepeat

按钮是否能够重复触发。

true 表示能够重复触发,false表示不能

相当于连续点击这个按钮。

autoRepetDelay重复触发的延时时间,按住按钮之后,多久开始重复触发
autoRepeatInterval重复触发的周期

 由于 QWidget 算是所有控件的父类,因此在上面说的所有属性QAbustractButton 中也有。

并且 Qt 的接口设计十分清晰,比如 shorCut 属性,想设置快捷键的 API 就是 setShortcut.

 可以在使用的时候自己多试试。

我们设置五个按钮,并且清空文本。

然后通过 QIcon 设置按钮图标。 

然后分别个下面的四个按钮设置槽函数。 

这样我们就能通过键盘来控制按钮,并且还能够设置按钮的图标。 

 Radio Button控件

Radio Button 是一个单选按钮,让我们在多个选项中选一个。

当然,QAbustractButton 中的所有属性它也有。

而 QAbustractButton 和 Radio Button 控件相关的属性有。

属性说明
checkable是否能选中
checked是否已经选中,checkable是checked的前提条件
autoExclusive

是否排他

选中一个按钮是否会取消其他按钮的选中

一般Radio Button 默认排他

我们设置一个文本框和三个 Radio Button 。

设置三个槽函数。 

 可以看到,选中一个按钮,其他的按钮就没有选中。

而如果我们设定某一个按钮是不可选中时,会发现该按钮依旧可以点击,槽函数会运行,但是不会被选中。

setCheckable 为 false

 

而如果是设置某个按钮 Enable 为false,则该按钮直接不可选中。

 Ra

按钮的四种触发模式

在 Qt 中,按钮一共有四个触发模式。

clicked :鼠标点击并且释放触发

pressed :鼠标点击触发

released :鼠标释放触发

toggled :  checked 属性更换触发

一般 Radio Button 是 toggled 模式触发。

按钮分组

 Radio Button 是默认排他的,但是有时候我们需要排他性,但是又不完全排他的性质。

比如肯德基点套餐,汉堡可以牛肉堡,鸡肉堡二选一,饮料雪碧可乐二选一之类的。

我们总不可能选了牛肉堡就不能选可乐了。

这就需要按钮分组了。

我们首选搞四个按钮,设置好名字。

然后通过 QButtonGroup 进行分组,将牛肉堡和鸡肉堡放一组,可乐和雪碧放一组。 

 可以看到,选择汉堡的时候,不会影响到饮品的选择。

CheckBox控件

上面了解了 Radio Button,是一个单选的控件,而CheckBox控件则是一个多选控件。

该控件的属性和 RadioButton类似,API也类似,因此不再阐述。

直接了解如何使用。

在 Qt Designer 选择三个 CheckBox,并且设置好名称。

 然后通过 connect 绑定对应的槽函数和信号。

对于复选框来说,每次选中或者取消选择,都会发送一个 stateChanged 信号,如果想让复选框状态改变时触发某一个行为,可以绑定这个信号。

当然,我们也可以通过 isChecked() 函数来判断是否变换了。 

 

可以看到选中和取消选中槽函数都被触发了。

我们新增几个控件,然后给 PushButton 按钮添加槽函数。

当点击确认按钮就修改 label 的文本。 

提交后发现确实修改了。 

显示类控件

Label控件

Label 是一个标签,可以显示图片或者文本。

有以下核心属性。

属性说明
textLabel 中的文本
textFormat

文本格式

Qt::PlainText 纯文本

Qt::RichText 富文本

Qt::MarkdownText markdown 格式

Qt::AutoText 自动识别文本格式

pixmapQLabel 中的图片
scaledContents

该属性为 true 表示内容自动拉伸填充

false 则不会拉伸填充

alignment

对齐方式

可以设置水平和垂直方向对齐

wordWrap

设置为 true 文本会自动换行

false 则不会自动换行

indent 

设置文本缩进,水平和垂直方向都有效

最多设置两个方向有效

具体哪两个方向取决于 alignment 属性

margin

内部文本和边框之间的边距

一般上下左右四个方向都同时有效

openExternalLinks

是否允许打开一个外部连接

如果文本是 url 时会需要

buddy 给 Qlabel 设置一个伙伴,点击 Qlabel 会激活伙伴

文本显示

我们设置三个标签。 

分别设置为普通文本,富文本,markdown文本,然后分别用不同的语法设置一段文本。 

能够看到不同的文本会按不同的语法解析文本,从而显示不同的文本。 

图片显示

我们先设置一个 Label 控件。

然后将它固定在窗口的左上角,并且 label 大小为窗口大小。

同时通过 setScaledContents 来让图片铺满 label。 

运行发现图片铺满了整个窗口。 

但是如果我们修改窗口大小,这个图片不会随着窗口变化而变化。 

这是因为这个图片只会铺满整个 label,而label又只在初始化铺满了窗口,后续窗口变换,label并没有变化。

而窗口变化实际上对应窗口的 resizeEvent 函数。

在 Qt 中,用户操作有两类概念,一个是信号,一个是事件,而 resizeEvent 也是一种事件。

而 resizeEvent 是 窗口类(MainWindow) 的父类 (QMainWindow)的一个函数,因此我们可以通过在 MainWindow 中重写 resizeEvent 类即可实现 label 随窗口改变而改变。

这也是C++的多态的一种应用。

先在头文件中声明函数。

 然后定义函数,即触发 resizeEvent 时,修改 label 大小,使其跟随窗口大小变化。

 此时图片是铺满 label 的,因此图片也会随着窗口变化而变化。

 label的对齐、缩进和边距

label 中的文本我们可以设置 alignment 属性。

alignment 属性一共有以下几种属性。

属性说明
Qt::AlignLeft水平靠左
Qt::AlignRight水平靠右
Qt::AlignHCenter水平居中
Qt::AlignJustify水平方向调整间距两端对齐
Qt::AlignTop垂直靠上
Qt::AlignButton垂直靠下
Qt::AlignVCenter垂直居中
Qt::AlignCenter居中,等价于 AlignVCenter | AlignHCenter

Label 中的文本的对齐可以同时在水平和垂直上进行操作。

水平方向的要求 | 垂直方向的要求 即可同时控制两个方向。

一般 label 默认水平靠左,垂直居中。

并且一般情况下,label 的文本是不能自动缩进的,如果文本过长,后面的文本会看不到,因此我们可以设置自动换行。

除此之外,还可以设置缩进、边距等,我们直接来试着设置一下。

首先整四个 label,为了更好的演示,给它们设置了边框。

边框:即QFrame,QLabel 的父类,可以自行设置 frameShape。

然后给四个 Label 分别设置 Aligenment、自动换行、首行缩进、边距等设置。

 //设置垂直水平居中文本
    ui->label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    ui->label->setText("这是一个垂直水平居中文本");

    //设置自动换行文本
    ui->label_2->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    ui->label_2->setWordWrap(true);
    ui->label_2->setText("这是一个可以自动换行文本这是一个可以自动换行文本这是一个可以自动换行文本这是一个可以自动换行文本这是一个可以自动换行文本");

    //设置首行缩进
    ui->label_3->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    ui->label_3->setIndent(20);
    ui->label_3->setText("这是一个设置了首行缩进的文本这是一个设置了首行缩进的文本这是一个设置了首行缩进的文本这是一个设置了首行缩进的文本这是一个设置了首行缩进的文本");

    //设置边距
    ui->label_4->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    ui->label_4->setMargin(20);
    ui->label_4->setText("这是一个设置了边距的文本这是一个设置了边距的文本这是一个设置了边距的文本这是一个设置了边距的文本这是一个设置了边距的文本这是一个设置了边距的文本");

都如预料中一样,label_1 居中了,label_2 换行了,label_3 有首行缩进,label_4 有边距。 

其中仔细观察 label_3 和 label_4 ,发现首行缩进只对左侧和上侧有效右侧和底测无效而边距则是四个方向都有效(只不过看不出来跟底部有边距罢了) 。

buddy

label 也可以设置伙伴。

label 设置成 快捷键 &A 的形式,虽然这里没显示出 &. 

不过这样就能通过 Alt + A 来选定第一个 label,同理 Alt + B 可以选定第二个 label.

Label 的 buddy 只能通过 Alt + 快捷键的方式响应,不能像 PushButton那样直接使用

然后可以在 Qt Designer 中设置 buddy,输入对应 buddy 的名称即可绑定。

也可以通过代码形式设置 buddy。 

 然后就能通过快捷键来选定对应的按钮。

 LCD Number控件

LCD Number 是一个显示数字的控件。

属性说明

intValue

以 int 形式显示数字 
value

以 double 形式显示数字

该value 和 intValue 是联动的,value 1.5 在 intValue 显示2.

而设置 intValue 和 value 的API 是 display

mode

数字形式

QLCDNumber::Dec : 十进制

QLCDNumber::Hex : 十六进制

QLCDNumber::Bin : 二进制

QLCDNumber::Oct : 八进制

segmentStyle

数字显示风格

QLCDNumber::Flat :平⾯的显⽰⻛格,数字呈现在⼀个平坦的表⾯上
QLCDNumber::Outline :轮廓显⽰⻛格,数字具有清晰的轮廓和阴影效果
QLCDNumber::Filled :填充显⽰⻛格,数字被填充颜⾊并与背景区分 开
digitCount显示几位数字
smallDecimalPoint设置比较小的小数点

接着我们通过 LCDNumber 设置一个计时器。

首先在头文件添加一个 QTimer 对象和一个函数。

 QTimer 对象在每一个时间间隔中都会发出一个 timeout 的信号,我们将该信号和我们创建的函数绑定在一起。

并且设置 QTimer 对象每过1秒响应一次,即时间间隔为1秒。

并且设置 lcdNumber 初识数字为3.

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->lcdNumber->display(3);
    timer = new QTimer(this);
    connect(timer,&QTimer::timeout,this,&MainWindow::UpdateTime);
    timer->start(1000);

}

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

void MainWindow::UpdateTime()
{
    int value = ui->lcdNumber->intValue();
    if(value <= 0)
    {
        timer->stop();
        return;
    }
    ui->lcdNumber->display(value - 1);
}

 而我们设定的函数则是获取 lcdNumber 的值,如果为0就退出,否则更新值为 value - 1.

可以看到确实成功了。

之前在 C++实现计时器的时候可以通过sleep + 循环的方式实现,这里呢?能否在构造函数中采用 sleep + 循环的方式实现一个计时器吗?答案是不行的。

像这样的代码形式

Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
 ui->setupUi(this);
 int value = ui->lcdNumber->intValue();
 while (true) {
 std::this_thread::sleep_for(std::chrono::seconds(1));
 if (value <= 0) {
 break;
 }
 ui->lcdNumber->display(value - 1);
 }
}

因为循环会导致构造函数无法完成,界面无法正确构造和显示。

那如果采用线程中采用 sleep + 循环呢

Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
 ui->setupUi(this);
 std::thread t([this]() {
 int value = 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上的操作,都必须在主线程中完成。像 connect 函数,构造函数都是在主线程上完成的。

这是因为GUI的修改牵一发而动全身,如果可以通过线程修改一个GUI,那么其他的东西也需要修改,如字体,颜色,样式等,这需要确定一定的顺序,而多线程无法保证顺序,因此 QT 直接 ban 了这种操作。

ProgressBar控件

该控件是一个进度条。

属性说明
minimum进度条最小值
maximum进度条最大值
value进度条当前值
alignment

文本在进度条中的对齐方式

Qt::AlignmentLeft 左对齐

Qt::AlignmentRight 右对齐

Qt::AlignmentCenter 居中对齐

Qt::AlignmentJustify 两端对齐

textVisble进度条的数字是否可见
orientation进度条方向是水平还是垂直
invertApperance是否朝反方向增长
textDirection文本的朝向
format

展示的数字格式

%p :表示进度的百分比 (1-100)

%v :表示进度的数值(1-100)

%m:表示剩余时间(以毫秒为单位)

%t:表示总时间(以毫秒为单位)

我们可以自己通过QT Designer 或者代码的形式更改进度条的形式。

和计时器一样,先设定一个定时器,和一个槽函数。

然后绑定 timeout 信号和这个槽函数。

而槽函数内部就是将进度条的数据+1.直到100; 

 可以看到确实从1到100的进度条了。

而颜色之类的我们也可以在QT Designer 中修改。

可以通过修改 styleSheet 修改。

不过需要注意,代码方式和这种方式只能二选一,不能既要又要哦。 

设置颜色的语言有很多种,像代码方式那样用 rgb 来表示可以,通过这种方式也是可以设置的。

chunk 是选中进度条中的每一块,即背景的颜色。

而 QProgressBar::text 则是选中数字,修改数字的颜色。

Calendar Widget控件

Calendar Widget 是一个日历控件。

属性说明
selectDate当前选中的日期
minimumDate最小日期
maximumDate最大日期
firstDayOfWeek每周的第一天是周几(即日历的第一列)
gridVisible是否显示表格的边框
selectionMode是否允许选择日期
navigationBarVisible日历上方标题是否显示
horizontalHeaderFormat日历上方标题显示日期格式
verticalHeaderFormat日历第一列显示的内容格式
dateEditEnabled是否允许日期被编辑
 日历的重要信号
信号说明
selectionChanged(const QDate&)当选中的日期发生改变时触发
activated(const QDate&)当双击一个有效的日期或者按下回车键时发出,形参的 QDate 保存了当前选中的日期
currentPageChanged(int,int)当年份月份改变时发出,形参表示改变后的新年分和月份

我们设立三个控件,projectName 分别是 label、label_2、calendarWidget 三个控件。 

然后为Calendar Widget 控件添加槽函数。

可以看到确实 label 的文本修改了,换页时 label_2 的文本被修改了。

输入类控件

LineEdit 控件

属性说明

text

输入框中的文本
inputMask

输入内容约束

可以约束输入的格式的形式

maxLength最大长度
frame是否添加边框
echoMode

显示方式

QLineEdit::Normal : 默认,能够显示出文本

QLineEdit::Password : 输入的文本会被 *  或者=替代

QLineEdit::NoEcho 输入的文本不会显示

cursorPosition当前光标的位置
alignment文字对齐方式,设置水平和垂直方向的对齐
dragEnabled是否允许拖拽
readOnly是否允许只读(不可修改)
placeHolderText输入框为空时,显示的提示信息
clearButtonEnabled是否自动显示 “清除按钮”

 核心信号

信号说明
void cursorPosition(int old,int new)当鼠标移动时发出信号,old 为之前的位置,new为现在的位置
void editingFinished()当按返回键和回车键时,或者行编辑失去焦点时,发出此信号
void returnPressed()

当按返回键和回车键时发出此信号

如果设置了验证器,则必须通过验证才能发出

void selectionChanged()当选中的文本改变时,发出该信号
void textChanged(cosnt QString& text)当QLineEdit的文本修改时发出信号,text是新文本,代码修改能够触发该信号
void textEdited(const QString& text)当QLineEdit的文本修改时发出信号,text是新文本,代码修改能够触发该信号

通过该控件,我们可以设置一个简单的登录界面。

在 QtDesigner 中设置如下界面。

分别给三个 lineEdit 控件设置文本,并且设置好对应的 echomode .

再给pushbutton按钮设置好槽函数。 

 就得到了如下的界面,并且设置了清除按钮的lineEdit控件可以一次性清空数据。

 

不过这里有一个问题,那就是电话号码是有自己的格式的,即有11位,开头是1,后面全是数字。

如果我们提交了一个错误的电话号码,就应该是无效的。

这里我们可以通过设置正则表达式来验证电话号码是否符合格式。

首先通过正则表达式创建一个 QRegExp 对象,其正则表达式是以1开头,共11个数字。

然后给 lineEdit_telphone 设置一个 validator(验证器),其中 QValidator有四种,我们用其中一种来设置验证器 。

因为我们用到正则表达式来验证,因此用 QRegExpValidator(QRegularExpressionValidator 和这个验证器类似,不过有匹配优化)

设置好验证器后,在输入的时候 lineEdit 会发出一个信号,通过捕捉该信号,再通过槽函数即可验证是否成功。

通过 lineEdit_telphone 的验证器的 validate 函数来验证文本是否符合格式,不过由于 参数分别是 QString& 和 int& ,因此需要通过一个 QString 对象来复制一下文本,int& 的参数没什么用,验证失败的时候该参数会返回验证失败的位置。

QValidator::State 有三个参数 Invalid(违法)、Intermediate(无法判断)、Accepptable(验证成功)

 

 在一般的登录界面上,一般可以显示出密码的内容,我们可以通过添加一个按钮实现。

添加了一个checkBox按钮。当它状态转换时就更换 lineEdit 的 EchoMode。

发现点击之后就能够看到密码了。

Text Edit控件

QTextEdit 是一个多行的输入框,也是一个富文本和 markdown 编辑器,在文本超过范围时提供滚动条。

属性说明
markdown输入框持有的内容,支持 markdown 格式,会自动将markdown文本渲染成html
html输入框持有的内容,支持大部分html标签,包括img、table等
placeHolderText输入框为空时提示内容
readOnly是否是只读的
undoRedoEnable

是否开启undo/redo功能

ctrl + z 为undo(撤销)

ctrl + y 为redo(恢复)

autoFormating

开启自动格式化

默认为AutoNone,即不开启格式化

AutoBulletList :自动创建项目列表,如 在最左侧列输入 * 号或者在现有表项中按 enter 键

AutoAll:启动所有格式化,不过只有 AutoBulletList

tabstopWidth按下缩进占多少空间
overwriteMode是否开启覆写(即无法从中间开始输入,只能覆盖)
acceptRichText是否接受富文本内容
verticalScrollBarPolicy

垂直方向滚动条出现的策略

Qt::ScrollBarAsNeeded :默认值, 根据需要出现

Qt::ScrollBarAlwaysOff: 总是关闭滚动条

Qt::ScrollBarAlwaysOn:总是显示滚动条

horizontalScrollBarPolicy

水平方向滚动条出现的策略

Qt::ScrollBarAsNeeded :默认值, 根据需要出现

Qt::ScrollBarAlwaysOff: 总是关闭滚动条

Qt::ScrollBarAlwaysOn:总是显示滚动条

核心信号

信号说明
textChanged()文本内容改变时触发
selectionChanged()选中范围改变时触发
cursorPositionChanged()光标移动时触发
undoAvailable(bool)进行undo操作时触发
redoAvailiable(bool)进行redo操作时触发
copyAvailiable(bool)文本被选中/取消选中时触发

我们可以测试一下各种信号。 

为 redo、undo、copy 和各种光标变化、文本变化添加槽函数。 

能够发现在输入的时候,redoavailiable 是false,而 undoavailiable则是 true。

而当按下 ctrl + z 进行undo操作后,undoavailiable 则是false、redoavailiable则是true。

而按下 ctrl + y 进行 redo 操作后, redoavailiable 则变成了false、undoavailiable 则是true。

这说明 undo 操作和 redo 操作是相互依赖的。

而如果选中了一批内容 copyavailiable 就成true,没有选中就成false了。

 Combo Box控件

核心属性

属性说明
currentText当前选中的文本
currentIndex

当前选中的条目下标

从0开始计算,如果没有选中,则为-1

editable

是否允许修改

为true时,该控件类似 QLineEdit,也可以设置validator

iconSize下拉框图标(小三角)的大小
maxCount最多允许有多少个条目

核心方法

方法说明
addItem(const QString&)添加一个条目
currentIndex()

获取当前条目的下标

从0开始计算,如果没有选中则为-1

currentText()获取当前条目的文本内容

核心信号

        

信号说明

activated(int)

activated(const QString& text)

当用户选择了一个选项时发出

即用户点开下拉框,并且鼠标滑过某个选项

但是没有做出选中时发出

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

编辑框中的文本改变时发出

editable为true时有效

我们先来使用一下 Combo box 的简单使用。

在Qt Designer 中添加一个 combobox

通过 addItem 方法添加几个条目。 

 这样就能够通过 combo box 右侧的下拉键来自由选择添加的条目。

不过一般这些条目都是从文件或者网络中获取。

这里我们创建一个 combo.txt 的文件。

然后通过文件流获取,由于获取的是string,而非 QString,因而在添加条目时需要通过函数转化一下 

能够看到确实如此。 

Spin Box控件

SpinBox是一个微调框,根据内容不同有 QSpinBox 和 QDoubleSpinBox 两个控件,不过两个使用方式都一样,不过一个是用于整型,一个是用于小数形式的。

由于二者的核心属性和信号都一样,因此这里只阐述 QSpinBox 控件。

SpinBox 控件不可输入负数

属性说明
value当前存储的数值
singleStep每次加减变化的数值
displayInteger采用的进制形式,为10则表示十进制
minimum最小值
maximum最大值
suffix后缀
prefix前缀
wrapping是否能够换行
frame是否带边框
alignment文字对齐方式
readOnly是否只读
buttonSymbol

按钮图标

  • UpDownArrows 箭头形式
  • PlusMinus 加减号形式
  • NoButtons 没有按钮
accerlerated按下按钮时是否为快速调整模式
correctionMode

输入有误时如何修正

  • QAbstractSpinBox::CorrectToPreviousValue : 输入一个无效值,自动变为上一个有效值。例如初始值为1,如果输入一个负数,自动变成1
  • QAbstractSpinBox::CorrectToNearestValue:输入一个无效值,自动变为最接近的有效值,例如输入一个负数,自动变成0
keyboardTrack

是否开启键盘追踪

  • true : 输入数字就会发出valueChanged() 和 textChanged() 信号
  • false:按下回车才会触发 valueChanged() 和 textChanged() 信号

 核心信号

信号说明
valueChanged()

SpinBox 的文本修改时触发

参数 int ,表示当前数值

textChanged()

SpinBox 的文本修改时触发

参数QString,表示当前的前缀和后缀

 我们随便整一个 SpinBox

设置它的 keyboardTrack 属性为true,即数字改变发送 valueChanged 信号,并通过槽函数输出

我们发现即便我们还在输入中,也会收到 valueChanged 信号。如果设置 keyboardTrack 属性为 false 则只有在按下 Enter 的时候发出信号。 

  

 Date Edit & Time Edit控件

有三种微调框

  • QDateEdit
  • QTimeEdit
  • QDateTimerEdit

这三种都类似,只了解一种即可。

我们来了解 QDateTimeEdit 控件。

属性说明
dateTime时间日期的值,如 2025/1/1 0:00:00
date单纯日期的值
time单纯时间的值
displayFormat

时间日期格式,如 y/m/d h:m:s

  • y : 年
  • m :月
  • d : 日
  • h:时
  • m:分
  • s : 秒

不同的语言中有不同的区别,使用的时候再去查找

minimunDateTime最小日期时间
maximumDateTime最大日期时间
timeSpec
  • Qt::LocalTime: 显示本地时间
  • Qt::UTC :显示世界时间
  • Qt::offsetFromUTC : 显示相对于世界时间的时差

核心信号

信号说明
timeChanged(QTime)时间改变时触发
dateChanged(QDate)日期改变时触发
dateTimeChanged(QDateTime)时间日期任意改变时触发

我们可以简单的做出一个日期计算器。 

设置两个 QdateTimeEdit ,分别是 old 和 new.

然后给 pushbutton 设置一个槽函数。

通过 QDateTime 对象获取到两个微调框的时间。

然后通过 daysTo 函数获取 从 new 到 old 的天数,secsTo 函数获取从new 到 old 的秒数,再通过 /3600 后获取有多少个小时,再 %24 来得到多少个小时,最后输出在 label 上。 

 发现确实成功获得数据了!

Dial 控件 

QDial 表示一个旋钮。

绘画软件中有一个重要的部分——调色板,它能够以旋钮的方式来调出画家想要的颜色,QDial 就是类似的旋钮。

属性说明
value持有的数值
minimum最小的数值
maximum最大的数值
singleStep按下方向键的时候改变的步长
pageStep按下 pageUp/pageDown 的时候改变的步长
sliderPosition界面上旋钮显示的初识位置
tracking

外观是否会跟踪数值变化

默认为 true,一般不需要修改

wrapping

是否允许循环调整

即超过最大值是否会回到最小值

notchesVisible是否显示刻度线
notchTarget

刻度线之间的相对位置

数字越大,刻度线越稀疏

核心信号

信号说明
valueChanged(int)数值改变时触发
rangeChanged(int,int)范围变化时触发

我们设置一个 dial 和 一个 label。 

设置好 dial 的初始值,可以循环。

给 dial 控件的 valueChanged 信号设置槽函数。 

可以看到确实成功了。 

 

 Slider控件

QSlider 是一个滑动条。

由于 QDial 和 QSlider 都继承自QAbstractSlider,因此用法其实类似。

属性说明
value当前的数值
minimum最小值
maximum最大值
singleStep按下方向键修改的步长
pageStep

按下 pageUp/pageDown 的时候改变的步长

sliderPosition滑动条显示的初识位置
tracking

外观是否跟随数值变化

默认为true

orientation滑动条的方向是水平还是垂直
invertedAppearance是否需要翻转滑动条的方向
tickPosition刻度的位置
tickInterval刻度的密集程度

核心信号

信号说明
valueChanged(int)数值改变时触发
rangeChanged(int,int)范围变化时触发

我们设置两个 Slider 控件,分别是垂直的和水平的。 

设置好初始值,由于verticalSlider(垂直滑动条) 是上大下小,因此设置翻转。

然后设置它们的槽函数。

水平的修改窗口的 width,垂直修改窗口的 height。

能够看到确实修改了窗口的大小。 

 

一般Slider控件默认可以通过 pageDown/pageUp 或者 方向键控制。

选中某个 Slider 控件即可通过这些按键来控制Slider控件。

我们也可以自定义快捷键。

这里定义了 "-" 和 "=" 两个快捷键,并绑定它们的槽函数。

这里只修改水平滑动条的数值。 

可以发现确实成功绑定了新的快捷键。 

 

多元素控件

在QT中提供一些多元素控件。

  • QListWidget
  • QListView
  • QTableWidget
  • QTableView
  • QTreeWidget
  • QTreeView 

xxWidget 都是 xxView 的子类,它们之间的区别是 xxView 是底层一点的实现,xxWidget 则是对 xxView 进行了封装。

xxView 是基于 MVC 设计的控件,它属于 MVC 机制中的 V,即视图,它只提供一个视图,而保存数据、以及数据和视图之间的交互不由它管,需要用户自己定义。

xxWidget 则是基于 xxView 的基础上,进行了封装,它内部有数据和控制器,不用用户自己定义,直接往 xxWidget 内部输入数据即可。

就比如用户使用 xxView 的时候,需要创建一个Model 对象(如QStandardModel) ,并且将Model对象和View对象绑定起来,这样修改Model对象的数据会影响View的显示,修改View的显示也会影响到Model的数据。

不过Widget对象则直接使用即可。

ListWidget控件

QListWidet是一个列表,其内部的选项都能选中。

属性说明
currentRow当前选中的行号
count一共有多少行
sortingEnabled是否允许倒序
isWrapping是否允许换行
itemAlignment元素对齐方式
selectRectVisible被选中的元素是否可见
spancing元素之间的间隔

核心方法

方法说明

addItem(const QString& label)

addItem(QListWidgetItem* item)

列表中添加元素
currentItem()返回当前选中的元素
setCurrentItem(QListWidgetItem* item)设置选中的元素
setCurrentRow(int row)设置选中第几行的元素

insertItem(const QString& label,int row)

insertItem(QListWidgetItem* item,int row)

在指定的行号插入元素
item(int row)返回第row行的元素
takeItem(int row)删除指定行的元素

核心信号

信号说明
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设置文本对齐方式

接下来我们使用下ListWidget控件。

拖拽一个 ListView,右键后选择变型为,变成ListWidget。

然后添加两个按钮和一个lineEdit。 

两个按钮的槽函数如下设置。 

发现确实能够新增或者删除元素。 

 

TableWidget控件

该控件是一个表格,有多行,每一行有多列,每一个单元格都是一个 QTableWidgetItem 对象。

 核心方法

方法说明
item(int row,int col)获取对应行、列的 QTableWidgetIten 对象
setItem(int row,int col,QTableWidget*)设置对应行、列为对应的元素
currentItem()返回被选中的元素
currentRow()返回被选中的元素是第几行
currentColumn()返回被选中的元素是第几列
row(QTableWidgetItem*)获取指定 item 是第几行
column(QTableWidgetItem* )获取指定的 item 是第几列
rowCount()获取行数
columnCount()获取列数
insertRow(int row)在第 row 行插入新行
insertColumn(int column)在第 column 列插入新列
removeRow(int row)删除第 row 行
removeColumn(int column)删除第 col 列
setHorizontalHeaderItem(int column,QTableWidget*)设定指定列的表头
setVerticalHeaderItem(int row,QTableWidget*)设定指定行的表头

该控件和 QTableWidgetItem 类关系密切,需要了解以下这个类。

QTableWidgetItem 类的核心信号

信号说明
cellClicked(int row,int column)点击单元格触发
cellDobleClicked(int row,int column)双击单元格触发

cellEntered(int row,int column)

鼠标进入单元格时触发
currentCellChanged(int row,int column,int previousROw,int previousColumn)选中不同单元格时触发

QTableWidgetItem 类的核心方法

方法说明
row()返回当前的行号
column()放回当前的列号
setText(const QString& str)设置文本
setTextAlignment(int)设置文本对齐
setIcon(const QIcon& icon)设置图标
setSelected(bool)设置被选中
setSizeHints(const QSize&)设置尺寸
setFont(const QFont&)设置字体

咱们设置一个 QTableWidget 控件,和四个按钮,以及一个 lienEdit。 

四个按钮的槽函数如下。 

可以看到确实成功的添加行、列、删除行、列了。 

 

TreeWidget控件

QTreeWidget 是一个树形控价,类似文件系统一样,其中每一个元素都是QTreeWidgetItem。

每一个 QTreeWidgetItem 可以包含多个文本和图标,一个文本或者图标算一列。

实际上 TreeWidget 更像一个 伪 ListWidget,它并不像一般的二叉树有根节点,而是从根节点的下一层开始计算的。

 因此如果直接调用 QTreeWidget 的函数实际上都是针对顶层节点进行操作。

如果想在顶层节点下添加节点就需要先获取顶层节点然后再对顶层节点添加子节点。

接下来了解一下QTreeWidget 的函数吧。

核心方法

方法说明
clear清空所有节点
addTopLevelItem(QTreeWidgetItem* item)新增顶层节点
topLevelItem(int index)获取下标为index 的顶层节点
topLevelItemCount()获取顶层节点的个数
indexOfTopLevelItem(QTreeWidgetItem* item)获取指定顶层节点的下标
takeTopLevelItem(int index)

删除指定下标的顶层节点

并且返回被删除的元素

currentItem()获取当前选中的节点
setCurrentItem(QTreeWidget* item)选中指定节点
setExpanded(bool)展开/关闭节点
setHeaderLabel(const QString& text)设定 TreeWidget 的名称

核心信号

信号说明
currentItemChanged(QTreeWidgetItem* current,QTreeWidgetItem* old)切换选中元素时触发
itemClicked(QTreeWidgetItem* item,int col)点击元素时触发
itemDoubleClicked(QTreeWidgetItem* item,int col)双击元素时触发
itemEntered(QTreeWidgetItem* item,int col)鼠标进入时触发
itemExpanded(QTreeWidgetItem* item)元素展开时触发
itemCollaspend(QTreeWidgetItem* item)元素折叠时触发

QTreeWidgetItem 属性

属性方法
text持有的文本
textAlignment文本对齐方式
icon持有的图标
font文本字体
hidden是否隐藏
disabled是否禁用
expand是否展开
sizeHint尺寸大小
selected是否选中

QTreeWidgetItem 方法

方法说明
addChild(QTreeWidgetItem* item)新增子节点
childCount()获取子节点的个数
child(int index)获取指定的子节点
takeChild(int index)删除指定的子节点
removeChild(QTreeWidgetItem* item)删除指定的子节点
parent()获取对应的父节点

了解了控件和元素的属性方法后,来试着直接使用一下。

选择QTreeWidget、LineEdit、pushButton三个控件

全部设置好。

 按钮的槽函数如下。

然后就能够成功添加节点或者顶层节点了。 

 容器类控件

容器类控件就是能够包含多个控件的控件,在容器类控件下的控件,他们的父节点应该是对应的容器类节点。

GroupBox控件

该控件是一个带有标题的分组框,它没有什么实际作用,只是用来界面美化的。

属性说明
title分组框的标题
alignment分组框内部内容的对齐方式
flat是否是扁平模式
checkable

是否可以选择

为 ture 时,前方多出一个可勾选的部分

checked描述分组框的选择状态(checkable必须为true)

有一点需要注意,分组框内部的控件的父节点是分组框本身,而非窗口。

Tab Widget 控件

QTabWidget 是一个标签页。

可以设置多页,然后每一页可以添加不同的Widget,通过页切换来选择不同的widget。

属性说明
tabPosition

标签页所在位置

  • North 上方
  • South 下方
  • West 左侧
  • East 右侧
currentIndex当前选中了第几个标签页
currentTabText当前选中标签的文本
currentTabName当前选中标签的名字
currentTabIcon当前选中标签的图标
currentTabToolTip当前选中标签的提示信息

tabsCloseable

标签页是否能够关闭
movable标签是否可以移动

核心信号

信号说明
currentChanged(int)标签页切换时触发,参数为被点击的标签页号
tabBarClicked(int)点击选项卡的标签条时触发,参数为被点击的选项卡编号
tabBarDoubleClicked(int)双击选项卡的标签条时触发,参数为被点击的选项卡编号
tabCloseRequest(int)在标签页关闭时触发,参数为被关闭的选项卡编号

有一点需要注意,Tab Widget 每一页都是一个 QWidget,点击标签页即可切换。

添加标签页也是新增一个 QWidget ,而这一页中的所有控件的父节点都应该是这个QWidget。

咱们添加两个按钮和一个 TabWidget 控件。 

可以看出确实成功了。 

 

布局管理器

 在Qt Designer 上进行的控件布局,一般都是绝对定位的,但是当控件很多的时候,就会很不方便,因此Qt 引入了 布局管理器(layout) 机制来解决上述问题。

垂直布局

QVBoxLayout,表示垂直布局管理器。

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上方边距
layoutButtonMargin下方边距
layoutSpacing相邻元素之间的边距

通过代码方式需要通过 addWidget 方法将控件添加到 管理器中。 

有一点需要注意,在创建项目时,需要采用 QWidget,而非QMainWindow。

这是因为 QMainWindow 默认自带一个 layout ,而一个Widget中只能存在一个 layout,因此不能使用 QMainWindow。

 可以看到,三个按钮垂直布局,并且可以随着窗口变化而变化。

在刚刚已经讲过,一个Widget只能有一个 layout,不过在QtDesigner 中我们能够创建多个布局管理器。

 但是这样的方式创建的layout,不会随着窗口变化而变化。

这是因为QTDesigner在创建layout时会自动创建一个QWidget。

在xml形式的ui文件中可以看到创建的QWidget,而这也是layout不会随着窗口变化的原因。

 水平布局

使用QHBoxLayout表示水平布局管理器。

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上方边距
layoutButtonMargin下方边距
layoutSpacing相邻元素之间的边距

用法和特性跟垂直布局管理器一样。

而垂直布局和水平布局二者可以互相嵌套。

二者互相嵌套就能够做出很复杂的界面了。 

网格布局 

QGridLayout,表明网格布局管理器。

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上方边距
layoutButtonMargin下方边距
layoutHorizontalSpacing相邻元素水平间距
layoutVerticalSpacing相邻元素垂直间距
layoutRowStretch行方向拉伸系数
layoutColumnStretch列方向拉伸系数

正如名字所说,该布局管理器是以网格方式排列的,因此它在 addWidget 时需要指定列和行。

如图所示。 

 如果我们将Widget全部放一行或者全部放一列,就会得到类似 水平布局或者垂直布局的结果。

不过也要注意,如果说设置了一个很大的值,但是这个值和上个值之间没有其他元素,那么中间也不会腾出其他控件。

比如之前只有3行,但是你如果添加一个在第10行的元素,它也是直接在第三行元素下面。

我们还可以设置每个按钮的拉伸系数。

这里设置第一列的拉伸系数为1,第二列不拉伸,第三列拉伸系数为3.

能够得到如下界面。 

 

 当然,我们也可以设置垂直的拉伸系数,不过有一个问题,那就是按钮的高度都是固定的,因此需要设置按钮的垂直方向的 sizePolicy 为 QSizePolicy::Expanding

QPushButton的尺寸策略

  • QSizePolicy::Ignored : 忽略控件尺寸
  • QSizePolicy::Minimum : 最小的尺寸为固定值,布局不会超过该值
  • QSizePolicy::Maximum : 最大的尺寸为固定值,布局不会超过该值
  • QSizePolicy::Prefered : 理想的尺寸为固定值,布局尽量接近该值
  • QSizePolicy::Expanding : 控件的尺寸随着空间调整,尽可能占据空间
  • QSizePolicy::Shrinking : 控件的尺寸随着空间调整,尽可能缩小

这样才能看到垂直拉伸的效果。 

 

 

表单布局

QFormLayout,是QGridLayout的一种特殊情况,专门用来实现两列表单的布局。

 

可以看到得到如下界面。 

 

Spacer

有时候需要在空间之间添加空白,这时候就需要 QSpacerItem 表示 。

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

可以看到按钮之间有间距。 

 

也可以在QtDesigner中添加。

 总结

目前我们了解了QT项目中大部分常用的控件,以及其属性、信号和方法,也算是正式入门Qt了。

不过本文并没有将所有的方法都写出来,不过实际上都挺简单的,各位使用到不熟的控件可以自行搜索用法。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker学习(4):部署web项目

一、部署vue项目 在home目录下创建项目目录 将打包好的vue项目放入该目录下&#xff0c;dist是打包好的vue项目 在项目目录下&#xff0c;编辑default.conf 内容如下&#xff1a; server {listen 80;server_name localhost; # 修改为docker服务宿主机的iplocation / {r…

24法考证件照要求|不合格原因汇总!

6月法考报名&#xff0c;大家一定要提前熟悉下电子证件照片要求‼️ ⚠️证件照注意事项 ▪️不得上传全身照、风景照、生活照、背带(吊带)衫照、艺术照、侧面照、不规则手机照等。 ▪️本人近三个月内彩色(红、蓝、白底色均可)正面免冠电子证件照片&#xff0c;照片必须清晰完…

人工智能为犯罪地下世界带来了巨大的生产力提升

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

MySQL--执行计划

一、执行计划 1.介绍 执行计划是sql在执行时&#xff0c;优化器优化后&#xff0c;选择的cost最低的方案 通过desc、explain可以查看sql的执行计划 2.如何查看执行计划 table语句操作的表&#xff0c;在多表时才有意义type查找类型possible_keys可能会用到的索引key最终选择的…

python ofd转pdf及图片

本文部分内容参考&#xff0c;如有侵权请联系删除&#xff1a;使用 easyofd 解析ofd 文件_python模块easyofd如何使用-CSDN博客 背景需求&#xff1a;需要将邮箱中得ofd格式发票提取出来转换成pdf或者图片。 在网上搜了发现使用pyofd包&#xff0c;安装之后使用各种问题&…

VXLAN小结

1.VXLAN:(组件虚拟网络的架构核心)虚拟扩展本地局域网&#xff0c;通过隧道的形式&#xff0c;将物理上有隔离的资源&#xff0c;在逻辑上连通起来&#xff0c;使其二层互通。 a.物理网络:指的是构成 VXLAN 连接的基础 IP 网络 b.逻辑网络:指的是通过 VXLAN 构建的虚拟网络 C.N…

腾讯Java社招面试题真题,最新面试题

Java中synchronized和ReentrantLock有什么区别&#xff1f; 1、锁的实现方式不同&#xff1a; synchronized是JVM层面的锁&#xff0c;主要依赖于监视器对象&#xff08;monitor&#xff09;实现。ReentrantLock是JDK层面的锁&#xff0c;通过Java代码实现&#xff0c;提供了更…

docker 上面安装 Nginx 以及设置访问 IP 就可以访问前端工程

docker 运行 Nginx 第一步&#xff1a;搜索下镜像 首先可以使用 docker search nginx 搜索 nginx 服务 docker search nginx相关控制台输出&#xff1a; NAME DESCRIPTION STARS OFFICIAL…

[OC]深拷贝与浅拷贝

深拷贝与浅拷贝 深拷贝与浅拷贝 深拷贝与浅拷贝定义按照类型说明非容器类对象的深拷贝与浅拷贝不可变字符串可变类型字符串 容器类对象的深浅拷贝自定义类对象的深浅拷贝容器类对象的完全深拷贝1.copyItems2.解档和归档 定义 深拷贝&#xff1a;简单来说就是创建一个与被复制对…

虚拟化技术[2]之存储虚拟化

存储虚拟化 存储虚拟化简介存储虚拟化一般模型存储虚拟化实现方式基于主机存储虚拟化基于存储设备存储虚拟化基于网络存储虚拟化 案例分析&#xff1a;VMFSVMFS功能 存储虚拟化简介 存储虚拟化&#xff1a;将存储网络中的各个分散且异构的存储设备按照一定的策略映射成一个统一…

webpack5生产模式

生产模式 生产模式准备 开发模式和生产模式有不同的 配置文件 2修改webpack.prod.js文件修改webpack.dev.js文件 修改webpack.dev.js文件 1》修改输出路径为undefined 2》将绝对路径进行修改&#xff0c;进行回退 此时文件的执行命令为 修改webpack.prod.js文件 1》修改绝…

LangChain笔记

很好的LLM知识博客&#xff1a; https://lilianweng.github.io/posts/2023-06-23-agent/ LangChain的prompt hub: https://smith.langchain.com/hub 一. Q&A 1. Q&A os.environ["OPENAI_API_KEY"] “OpenAI的KEY” # 把openai-key放到环境变量里&…

【Linux】Linux的基本指令_2

文章目录 二、基本指令8. man9. nano 和 cat10. cp11. mv12. echo 和 > 和 >> 和 <13. more 和 less14. head 和 tail 和 | 未完待续 二、基本指令 8. man Linux的命令有很多参数&#xff0c;我们不可能全记住&#xff0c;我们可以通过查看联机手册获取帮助。访问…

深入编程逻辑:从分支到循环的奥秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、编程逻辑的基石&#xff1a;分支与循环 分支逻辑详解 代码案例&#xff1a;判断整数是…

Unity 资源 之 限时免费的Lowpoly农场动物,等你来领!

Unity资源 之 Lowpoly farm animals 农村动物 前言资源包内容领取兑换码 前言 Unity 资源商店为大家带来了一份特别的惊喜——限时免费的农场动物资源&#xff01;这是一个充满趣味和实用性的资源包。 资源包内容 在这个资源包中&#xff0c;你可以找到丰富多样的低地养殖动物…

685. 冗余连接 II

685. 冗余连接 II 问题描述 在本问题中&#xff0c;有根树指满足以下条件的 有向 图。该树只有一个根节点&#xff0c;所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点&#xff0c;而根节点没有父节点。 输入一个有向图&#xff0c;该…

mac 安装Node.js

文章目录 前言一、Node是什么&#xff1f;二、下载三、安装四、验证总结 前言 Node.js是一个开源、跨平台的JavaScript运行时环境&#xff0c;它允许开发者在服务器端运行JavaScript代码。Node.js是基于Chrome V8 JavaScript引擎构建的&#xff0c;它的设计目标是提供一种高效…

这样的直男程序员,活该你单身一万年!

#分享下相亲时遇到过哪些奇葩现象# 这样的直男程序员&#xff0c;活该你单身一万年&#xff01; 在丛丛脱单小程序上相亲&#xff0c;遇到一个程序员妹纸&#xff0c;于是有了如下的真实故事&#xff1a; 妹子说她是程序员来着&#xff0c;想着我也是程序员&#xff0c;就想交…

基于xilinx FPGA的 FFT IP使用例程说明文档(可动态配置FFT点数,可计算信号频率与幅度)

目录 1 概述2 IP examples功能3 IP 使用例程3.1 IP设置3.2 fft_demo端口3.3 例程框图3.4 仿真结果3.5 仿真验证得出的结论4 注意事项5例程位置 1 概述 本文用于讲解xilinx IP 的FFT ip examples的功能说明&#xff0c;方便使用者快速上手。 参考文档&#xff1a;《PG109》 2 …

MySQL大表删除方案

1.问题 在生产环境中&#xff0c;执行大表删除操作时&#xff0c;很容易因为占用了大量io资源导致其他事务被阻塞&#xff0c;最终事务不断堆积导致MySQL挂掉。 2.drop命令 drop命令&#xff0c;MySQL主要干了两件事&#xff1a; 清除buffer pool缓冲&#xff08;内存&…