【QT】控件一(QWidget、Button、Label)

文章目录

  • [1. Qwidget核心属性](#1. Qwidget核心属性)
    • [1.1 enable](#1.1 enable)
    • [1.2 geometry](#1.2 geometry)
    • [1.3 windowTitle](#1.3 windowTitle)
    • [1.4 windowIcon](#1.4 windowIcon)
    • [1.5 windowOpacity](#1.5 windowOpacity)
    • [1.6 cursor](#1.6 cursor)
    • [1.7 font](#1.7 font)
    • [1.8 toolTip](#1.8 toolTip)
    • [1.9 focusPolicy](#1.9 focusPolicy)
    • [1.10 styleSheet](#1.10 styleSheet)
  • [2. 按钮类控件](#2. 按钮类控件)
    • [2.1 Push Button](#2.1 Push Button)
    • [2.2 Radio Button](#2.2 Radio Button)
    • [2.3 Check Box](#2.3 Check Box)
  • [3. 显示类控件](#3. 显示类控件)
    • [3.1 Label](#3.1 Label)
    • [3.2 LCD Number](#3.2 LCD Number)
    • [3.3 ProgressBar](#3.3 ProgressBar)
    • [3.4 Calendar Widget](#3.4 Calendar Widget)

控件是构成⼀个图形化界面的基本要素

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

1. Qwidget核心属性

在 Qt 中,使用 QWidget 类表示 "控件",像按钮、视图,输入框,滚动条等具体的控件类,都是继承自QWidget

可以说,QWidget 中就包含了 Qt 整个控件体系中,通用的部分。

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

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

下面我们就来认识一下常用的属性:

1.1 enable

API 说明
isEnabled() 获取到控件的可⽤状态
setEnabled 设置控件是否可使⽤, true 表⽰可⽤,false 表⽰禁⽤

所谓 "禁用" 指的是该控件不能接收任何用户的输⼊事件,并且外观上往往是灰色的;如果⼀个 widget 被禁用,则该 widget 的⼦元素也被禁用

在 Qt Designer 中创建按钮的时候,可以设置按钮的初始状态是 "可用" 还是 "禁用"

1.2 geometry

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

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

但是实际开发中,我们并不会直接使⽤这⼏个属性,⽽是通过⼀系列封装的⽅法来获取/修改

API 说明
geometry() 获取到控件的位置和尺寸,返回结果是⼀个 QRect ,包含了 x, y, width, height。 其中 x, y 是左上⻆的坐标.
setGeometry(QRect) 设置控件的位置和尺⼨,可以直接设置⼀个 QRect
setGeometry(int x, int y, int width, int height) 设置控件的位置和尺⼨,分四个属性单独设置.

下面我们来使用一下:

下面我们实现:只要点击不想的按钮,按钮就跑了的效果

window frame 的影响

如果 widget 作为⼀个窗⼝ (带有标题栏,最⼩化, 最⼤化, 关闭按钮),那么在计算尺⼨和坐标的时候就有两种算法:包含 window frame 和 不包含 window frame.

  • 其中 x(), y(), frameGeometry(), pos(), move() 都是按照包含 window frame 的⽅式来计算的.
  • 其中 geometry(), width(), height(), rect(), size() 则是按照不包含 window frame 的⽅式来计算的.

下面我们写个代码感受 geometry 和 frameGeometry 的区别:

  • 构造方法 中,Widget 刚刚创建出来,还没有加⼊到对象树中,此时也就不具备 Window frame.
  • 在按钮的 slot 函数中,由于⽤⼾点击的时候,对象树已经构造好了,此时 Widget 已经具备了 Window frame,因此在位置和尺⼨上均出现了差异

1.3 windowTitle

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

注意! 上述设置操作针对不同的 widget 可能会有不同的⾏为。如果是顶层 widget (独立窗口),这个操作才会有效;如果是子 widget,这个操作无任何效果

1.4 windowIcon

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

注意!仅针对顶层 widget 有效.

注意: Windows 下路径的分隔符可以使⽤ / 也可以使⽤ \ . 但是如果在 字符串 中使⽤ \ , 需要写作转义字符的形式 \\ . 因此我们还是更推荐使⽤ /

实际开发中, 我们⼀般不会在代码中通过绝对路径引⼊图⽚. 因为我们⽆法保证程序发布后, ⽤⼾的电脑上也有同样的路径.

如果使⽤相对路径, 则需要确保代码中的相对路径写法和图⽚实际所在的路径匹配 (⽐如代码中写作 "./image/watermelon.jpg", 就需要在当前⼯作⽬录中创建 image ⽬录, 并把 watermelon.jpg 放进去).

Qt 使⽤ qrc 机制帮我们解决了文件的路径问题,更⽅便的来管理项⽬依赖的静态资源

  • qrc 文件是⼀种XML格式的资源配置⽂件,它用XML记录硬盘上的⽂件和对应的随意指定的资源名称,应⽤程序通过资源名称来访问这些资源.
  • 在Qt开发中,可以通过将资源⽂件添加到项⽬中来⽅便地访问和管理这些资源,这些资源⽂件可以位于qrc⽂件所在⽬录的同级或其⼦⽬录下.
  • 在构建程序的过程中,Qt 会把资源⽂件的⼆进制数据转成 cpp 代码,编译到 exe 中,从⽽使依赖的资源变得 "路径⽆关".

注意上述路径的访问规则.

  • 使用 : 作为开头, 表⽰从 qrc 中读取资源.
  • / 是上⾯配置的前缀
  • rose.jpg 是资源的名称

需要确保代码中编写的路径和添加到 qrc 中资源的路径匹配,否则资源⽆法被访问 (同时也不会有报错提⽰).

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

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

上述 qrc 这⼀套资源管理⽅案, 优点和缺点都很明显.

  • 优点:确保了图片、字体、声⾳等资源能够真正做到 "⽬录⽆关",⽆论如何都不会出现资源丢失的情况.
  • 缺点:不适合管理体积大的资源,如果资源⽐较大 (⽐如是⼏个 MB 的⽂件), 或者资源特别多,⽣成的最终的 exe 体积就会⽐较⼤,程序运⾏消耗的内存也会增⼤, 程序编译的时间也会显著增加.

1.5 windowOpacity

API 说明
windowOpacity() 获取到控件的不透明数值. 返回 float, 取值为 0.0 --1.0 其中 0.0 表⽰全透明, 1.0 表⽰完全不透明.
setWindowOpacity(float n) 设置控件的不透明数值

同时控制台中也可以看到 opacity 数值的变化,C++ 中 float 类型遵守 IEEE 754 标准,因此在进⾏运算的时候会有⼀定的精度误差,因此 1 -0.1 的数值并非是 0.9

1.6 cursor

API 说明
cursor() 获取到当前 widget 的 cursor 属性,返回 QCursor 对象,当⿏标悬停在该 widget 上时,就会显⽰出对应的形状.
setCursor(const QCursor& cursor) 设置该 widget 光标的形状. 仅在⿏标停留在该 widget 上时⽣效
QGuiApplication::setOverrideCursor(const QCursor& cursor) 设置全局光标的形状. 对整个程序中的所有 widget 都会⽣效, 覆盖上⾯的 setCursor 设置的内容
  1. 在 Qt Designer 中设置按钮的光标
  1. 通过代码设置按钮的光标

Qt ⾃带的光标形状有限. 我们也可以⾃⼰找个图⽚, 做成⿏标的光标.

1.7 font

属性 说明
family 字体家族. ⽐如 "楷体", "宋体", "微软雅⿊" 等.
pointSize 字体⼤⼩
weight 字体粗细. 以数值⽅式表⽰粗细程度取值范围为 0, 99, 数值越⼤, 越粗.
bold 是否加粗. 设置为 true, 相当于 weight 为 75. 设置为 false 相当于 weight 为 50
italic 是否倾斜
underline 是否带有下划线
strikeOut 是否带有删除线
  1. 使用QT designer

  2. 使用代码

1.8 toolTip

API 说明
setToolTip() 设置 toolTip. ⿏标悬停在该 widget 上时会有提⽰说明.
setToolTipDuring() 设置 toolTip 提⽰的时间. 单位 ms. 时间到后 toolTip ⾃动消失.

toolTip 只是给⽤⼾看的,在代码中⼀般不需要获取到 toolTip.

1.9 focusPolicy

设置控件获取到焦点的策略。

比如某个控件能否用鼠标选中或者能否通过 tab 键选中

所谓 "焦点", 指的就是能选中这个元素,接下来的操作 (比如键盘操作),就都是针对该焦点元素进⾏的了,这个对于输⼊框、单选框、复选框等控件非常有用的

API 说明
focusPolicy() 获取该 widget 的 focusPolicy,返回 Qt::FocusPolicy
setFocusPolicy(Qt::FocusPolicy policy) 设置 widget 的 focusPolicy

Qt::FocusPolicy 是⼀个枚举类型,取值如下

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


1.10 styleSheet

通过 CSS 设置 widget 的样式

CSS 中可以设置的样式属性非常多,基于这些属性 Qt 只能⽀持其中⼀部分,称为 QSS

使用代码设置样式:

2. 按钮类控件

2.1 Push Button

使⽤ QPushButton 表示⼀个按钮,这也是当前我们最熟悉的⼀个控件了; QPushButton 继承自QAbstractButton,这个类是⼀个抽象类,是其他按钮的⽗类 。

QAbstractButton 继承自QWidget,所以前面我们介绍的QWidget的各种属性、函数的使用方法,在这里也都是有效的。

在QAbstractButton 中,和 QPushButton 相关性较大的属性如下:

属性 说明
text 按钮中的⽂本
icon 按钮中的图标
iconSize 按钮中图标的尺⼨
shortCut 按钮对应的快捷键
autoRepeat 按钮是否会重复触发. 当⿏标左键按住不放时, 如果设为 true, 则会持续产⽣⿏标点击事件; 如果设为 false, 则必须释放⿏标, 再次按下⿏标时才能产⽣点击事件. ( "连发" 效果)
autoRepeatDelay 重复触发的延时时间. 按住按钮多久之后, 开始重复触发
autoRepeatInterval 重复触发的周期

下面我就就来实现一个方向键按钮的效果


调整图标大小

设置快捷键与重复触发

2.2 Radio Button

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

作为 QAbstractButton 和 QWidget 的子类,上⾯介绍的属性和用法,对于 QRadioButton 同样适用

QAbstractButton 中和 QRadioButton 关系较大的属性

属性 说明
checkable 是否能选中
checked 是否已经被选中. checkable 是 checked 的前提条件.
autoExclusive 是否排他,选中⼀个按钮之后是否会取消其他按钮的选中,对于 QRadioButton 来说默认就是排他
  1. 在界⾯上创建⼀个 label 和 3 个 单选按钮,实现选择性别
  1. 设置默认值 与 不可选
  1. click、press、release、toggled 的区别

QRadioButton提供了四个槽函数

  • clicked 表示⼀次 "点击" (是⼀次⿏标按下+⿏标释放触发的)
  • pressed 表示鼠标 "按下" (是⿏标按下触发的)
  • released 表示鼠标 "释放" (是⿏标释放触发的)
  • toggled 表示按钮状态切换 (是 checked 属性改变时触发的

总的来说,toggled 是最适合 QRadioButton 的

  1. 分组

此时直接运⾏程序,可以看到, 这六个 QRadioButton 之间都是排他的;我们希望每⼀组内部来控制排他,但是组和组之间不能排他.

引入 QButtonGroup 进行分组

2.3 Check Box

QCheckBox 表示复选按钮,可以允许选中多个

和 QCheckBox 最相关的属性也是 checkable 和 checked,都是继承自QAbstractButton

3. 显示类控件

3.1 Label

QLabel 可以用来显示文本和图片,核心属性如下:

属性 说明
text QLabel 中的⽂本
textFormat ⽂本的格式。Qt::PlainText 纯⽂本、Qt::RichText 富⽂本(⽀持 html 标签) 、Qt::MarkdownText markdown 格式、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 就会被选中.
  1. 文本格式
  1. 显示图片

虽然 QPushButton 也可以通过设置图标的⽅式设置图⽚, 但是并⾮是⼀个好的选择. 更多的时候还是希望通过 QLabel 来作为⼀个更单纯的显⽰图⽚的⽅式.

使图片自动拉伸

此时,如果拖动窗口大小,可以看到图片并不会随着窗口大小的改变而同步变化.

为了解决这个问题,可以在 Widget 中重写 resizeEvent 函数

注意:

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

QFrame 是 QLabel 的⽗类. 其中 frameShape 属性⽤来设置边框性质.

  • QFrame::Box :矩形边框
  • QFrame::Panel :带有可点击区域的⾯板边框
  • QFrame::WinPanel :Windows⻛格的边框
  • QFrame::HLine :⽔平线边框
  • QFrame::VLine :垂直线边框
  • QFrame::StyledPanel :带有可点击区域的⾯板边框,但样式取决于窗⼝主题

下面是枚举类型Alignment的部分值,具体内容请查看文档

  1. 设置伙伴

此处把 label 中的⽂本设置为 "快捷键 &A" 这样的形式,其中 & 后⾯跟着的字符,就是快捷键.

可以通过 alt + A 的方式来触发该快捷键.

但是注意,这里的快捷键和 QPushButton 的不同。需要搭配 ALT 键 和 单个字母的方式才能触发

3.2 LCD Number

QLCDNumer 是⼀个专门用来显示数字的控件,类似于 "老式计算器" 的效果

属性 说明
intValue QLCDNumber 显⽰的数字值(int)
value QLCDNumber 显⽰的数字值(double)。 和 intValue 是联动的,例如给 value 设为 1.5, intValue 的值就是 2. 另外, 设置 value 和 intValue 的⽅法名字为 display,⽽不是 setValue 或者 setIntValue .
digitCount 显⽰几位数字
mode 数字显⽰形式. QLCDNumber::Dec :⼗进制模式,显⽰常规的⼗进制数字。 QLCDNumber::Hex :⼗六进制模式,以⼗六进制格式显⽰数字。 QLCDNumber::Bin :⼆进制模式,以⼆进制格式显⽰数字。 QLCDNumber::Oct :⼋进制模式,以⼋进制格式显⽰数字。 只有⼗进制的时候才能显⽰⼩数点后的内容
segmentStyle 设置显⽰⻛格。QLCDNumber::Flat :平⾯的显⽰⻛格,数字呈现在⼀个平坦的表⾯上。 QLCDNumber::Outline :轮廓显⽰⻛格,数字具有清晰的轮廓和阴影效果。 QLCDNumber::Filled :填充显⽰⻛格,数字被填充颜⾊并与背景区分开
smallDecimalPoint 如果为true,则在两个数字位置之间绘制小数点。否则,它将占据自己的数字位置,即在数字位置上绘制。默认为false

下面,我们使用LCDNumber,实现一个倒计时

上述代码如果直接在 Widget 构造函数中,通过⼀个循环 + sleep 的方式是否可以呢?

cpp 复制代码
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);
	}
}

循环会使 Widget 的构造函数⽆法执⾏完毕, 此时界⾯是不能正确构造和显⽰的

上述代码如果是在 Widget 构造函数中,另起⼀个线程,在新线程中完成循环 + sleep 是否可以呢?

  • 这个代码同样是不⾏的, Qt 中规定,任何对于 GUI 上内容的操作,必须在主线程中完成,像 Widget 构造函数, 以及 connect 连接的 slot 函数,都是在主线程中调⽤的
  • 当我们⾃⼰的线程中尝试对界⾯元素进⾏修改时,Qt 程序往往会直接崩溃
  • 这样的约定主要是因为 GUI 中的状态往往是牵⼀发动全⾝的, 修改⼀个地⽅, 就需要同步的对其他内容进⾏调整;
  • 由于多线程执⾏的顺序⽆法保障,因此Qt 从根本上禁⽌了其他线程修改 GUI 状态,避免后续的⼀系列问题

后续如果我们也有类似的需要 "周期性修改界⾯状态" 的需求,也需要优先考虑使⽤定时器

其它属性

3.3 ProgressBar

使用 QProgressBar 表示⼀个进度条

属性 说明
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 :表⽰总时间(以毫秒为单位)

在实际开发中,进度条的取值,往往是根据当前任务的实际进度来进⾏设置的。

不要忘了,QProgressBar 同样也是 QWidget 的⼦类,因此我们可以使⽤ styleSheet 通过样式来修改进度条的颜色

3.4 Calendar Widget

QCalendarWidget 表⽰⼀个 "日历"

属性 说明
selectDate 当前选中的⽇期
minimumDate 最小日期
maximumDate 最大日期
firstDayOfWeek 每周的第⼀天(也就是⽇历的第⼀列) 是周⼏.
gridVisible 是否显⽰表格的边框
selectionMode 是否允许选择⽇期
navigationBarVisible 日历上⽅标题是否显⽰
horizontalHeaderFormat 日历上⽅标题显⽰的⽇期格式
verticalHeaderFormat 日历第⼀列显⽰的内容格式
dateEditEnabled 是否允许⽇期被编辑

重要信号

属性 说明
selectionChanged(const QDate&) 当选中的⽇期发⽣改变时发出
activated(const QDate&) 当双击⼀个有效的⽇期或者按下回⻋键时发出,形参是⼀个QDate类型,保存了选中的⽇期
currentPageChanged(int, int) 年份⽉份 改变时发出,形参表⽰改变后的新年份和⽉份

如需了解其它属性,请查阅官方文档

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript