【Qt】控件 QWidget

控件 QWidget

一. 控件概述

编程,讲究的是 "站在巨人的肩膀上",而不是 "从头发明轮子"。

  • Widget 是 Qt 中的核心概念,英文原义是 "小部件",我们此处也把它翻译为 "控件",控件是构成一个图形化界面的基本要素。
  • 一个图形化界面上的内容,不需要我们全都从零去实现,Qt 中已经提供了很多内置的控件了 (按钮、文本框、单选按钮、复选按钮、下拉框),我们拿过来就可以使用。
  • 上古时期,开发 GUI,没啥控件概念,界面上显示出来的东西,全部都是 "画" 出来的。
    • 显示器显示的内容,可以理解成 "画布",操作系统,就可以提供一些 API,让你在 "画布" 上进行画点、线、矩形、三角形等等,以及填充各种颜色。
    • 这个时候,开发一个图形化界面的程序,就相当于先画出一个矩形窗口。
    • 这种风格的开发,其实已经非常古老了。
  • 后来,控件这样的概念就逐渐被引入了,早起的控件比较简单,数量页比较有限。
    • 例如:HTML,包含很多标签,不同的标签有不同的效果。
      • 图片:< img >、链接:< a >、输入框:< input >、按钮:< button >
  • 随着时代的发展,新的 GUI 开发体系越来越丰富,提供的控件数量/质量越来越好了。
    • 例如:前端开发的知名框架 Element,整体来说,种类和效果都大幅度的提升了。
  • Qt 的控件虽然很多,但是整体来说,颜值还是比更现代的控件体系,要逊色一些。
    • Qt Designed 中展示的控件都是默认的样子。
    • Qt 还提供了一些优化手段,可以让控件变得更好看。
    • Qt 近几年还提供了 Qt Design Studio,对标的就是现代化的界面体系,制作出来的界面的美观程度就是业界最领先的一档,但是时要收费的。
    • 开发图形化界面程序,颜值确实还是一个挺重要的事情,往往会有专业的美工,先来设计更好看的界面,再交给程序员实现出来。
  • Qt 作为一个成熟的 GUI 开发框架,内置了大量的常用控件,如下图。
    • 这一点在 Qt Designer 中就可以看到端倪。
    • Qt 也提供了 "自定义控件" 的能力,可以让程序员在现有控件不能满足需求的时候,对现有控件做出扩展,或者手搓出新的控件。

综上,学习 Qt,其中一个很重要的任务就是熟悉并掌握 Qt 内置的常用控件,这些控件对于我们快速开发出符合需求的界面,是至关重要的。

二. QWidget 的核心属性

在 Qt 中,使用 QWidget 类表示 "控件"

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

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

  • 这些属性既可以通过 Qt Designer 直接修改,也可以通过代码的方式修改。
  • 这些属性的具体含义,在 Qt Assistant 中均有详细介绍。
    • 在 Qt Assistant 中搜索 QWidget,即可找到对应的文档说明
    • 或者在 Qt Creator 代码中,选中 QWidget,按 F1 也可。

可用状态:enabled

API 说明
isEnabled() 获取控件的可用状态
setEnabled() 设置控件是否可使用。true 表示可用,false 表示禁用
  • 所谓 "禁用" 指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。
  • 如果一个 Widget 被禁用,则该 Widget 的子元素也被禁用。

代码:创建一个禁用状态的按钮。

代码:通过按钮2,切换按钮1为的可用状态。

在同一个界面中,要求不同的控件的 objectName 也是必须是不同的,后续就可以通过 ui->objectName 方式来获取到对应的控件对象了,以下是通过拖拽的方式添加按钮控件,且自动生成控件对象的名称。

  • ui->pushButton 这是第一个按钮控件对象。
  • ui->pushButton_2 这是第二个按钮控件对象。
  • 元编程:Qt Designer 生成的 widget.ui 文件,本身是 XML 格式的,qmake 会把这个 XML 文件转换成 C++ 的 ui_widget.h 文件,生成的过程中就会感知到,界面上都存在哪些控件,且为每一个控件设置一个 objectName
  • 当前自动生成的 objectName 存在规律:控件类型_数字。很明显,以数字的方式命名,并不是一个好的编程习惯,我们也可以修改控件的名称。

右键点击两个按钮,点击转到槽,为 clicked 信号添加槽函数,此时不需要 connect

  • QPushButton 提供的信号还是挺多的,最常用的就是 clicked,它存在两个版本。
    • 无参版本:一般对于 QPushButton 来说,使用无参版本即可。
    • 有参版本:参数 bool check,表示是否被勾选,这个东西对于 QPushButton 没有意义。

最终结果:点击第一个按钮,执行对应的槽函数,点击第二个按钮,执行对应的槽函数 (若第一个按钮是可用的,则设置禁用,若第一个按钮是禁用的,则设置可用)

几何:geometry

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

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

但是实际开发中,我们并不会直接使用这几个属性,而是通过一系列封装的方法来获取/修改。对于 Qt 的坐标系,不要忘记是一个 "左手坐标系",其中坐标系的原点是当前元素的父元素的左上角。

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

move 只是修改控件的位置,setGeometry 修改控件的位置和尺寸。

控制按钮的位置

五个按钮的 objectName 分别为 pushButton_target、pushButton_up、pushButton_down、pushButton_left、pushButton_right,且五个按钮的初始位置和大小都随意。

  • 修改控件的名称时,需要点击那个控件,然后在 objectName 后面,写上你要的名称。

添加上下左右,这四个按钮的点击信号对应的槽函数,并补全代码如下:

  • qDebug() << rect 输出的结果:(x, y, width*height)
  • 最终效果:疯狂点击 left 和 up,达到的效果是,按钮的左上角的位置往左上走,但是右下角的位置不变,导致高度和宽度变大了。

如果想让这个按钮能够平移 (高度和宽度不变,整个按钮的位置都发生改变):

  • 上述的代码,修改的是 QRect 对象的 x 和 y,这样的修改就会使 QRect 的宽度和高度发生变换。
  • 通过 QRect 基于 setGeometry 第二个版本的函数重新设置位置即可。
  • 上述代码使用 move 方法也是可以的。
  • 最终效果:疯狂点击 left 和 up,达到的效果是,按钮的左上角的位置和右下角的位置同时往左上走。

简单的表白程序

往界面上拖拽两个按钮 PushButton 和一个 Label,设置 PushButton 的名称为 pushButton_accept 和 pushButton_reject,并且如下图:

为按钮设置点击操作的槽函数,如下:

  • rand() 是 C 标准库中能够生成随机数的函数,使用之前需要通过 time() 函数设置随机种子,C 语言中 time() 函数可以获取秒级别时间戳 (以1970年1月1日0时0分0秒为基准,计算当前时刻和基准时刻的秒数之差)
  • 按钮提供的信号不止有点击 clickede (按下和松开),使用 pressed 信号,就是鼠标按下时就触发对应的槽函数。
  • 也可以做到鼠标不点击,只要挪动到按钮上,就会让按钮挪动 mouseMoveEvent,需要用到 Qt 中的事件机制 (需要自定义类继承 QPushButton,重写 mouseMoveEvent 方法)
  • 最终效果:按钮残忍拒绝按钮,它会乱跑。

windows frame 窗口框架的影响

  • windows frame 是操作系统自带的,此时存在一个问题,按钮的位置是以父元素 Widget 窗口,还是以包含 window frame 为标准的。
    • widget 作为一个窗口 (带有标题栏,最小化,最大化,,关闭按钮),那么在计算尺寸和坐标的时候就有两种算法:包含 window frame 和不包含 window frame
  • 其中 x()、y()、frameGeometry()、pos()、move() 都是按照包含 window frame 的方式来计算的。
  • 其中 geometry()、width()、height()、rect()、size() 则是按照不包含 window frame 的方式来计算的。
  • 当然,如果是一个控件,上述两类方式得到的结果是一致的,因为它们不是一个窗口。

相关 API 如下:

API 说明
x() 获取横坐标 (包含 window frame)
y() 获取纵坐标 (包含 window frame)
pos() 返回 QPoint 对象,里面包含 x()、y()、setX()、setY() 等方法 (包含 window frame)
frameSize() 返回 QSize 对象,里面包含 width()、height()、setWidth()、setHeight() 等方法 (包含 window frame)
frameGeometry() 返回 QRect 对象,QRect 相当于 QPoint 和 QSize 的结合体,可以获取以及设置 x、y、width、size (包含 window frame)
width() 获取宽度 (不包含 window frame)
height() 获取高度 (不包含 window frame)
size() 返回 QSize 对象,里面包含 width()、height()、setWidth()、setHeight() 等方法 (不包含 window frame)
rect() 返回 QRect 对象,QRect 相当于 QPoint 和 QSize 的结合体,可以获取以及设置 x、y、width、size (不包含 window frame)
geometry() 返回 QRect 对象,QRect 相当于 QPoint 和 QSize 的结合体,可以获取以及设置 x、y、width、size (不包含 window frame)
setGeometry() 直接设置窗口的位置和尺寸,可以设置 x、y、width、height,或者 QRect 对象 (不包含 window frame)

其实这里的 API 有 frameGeometry 和 geometry 两个就足够完成所有的需求了。

代码:感受 geometry 和 frameGeometry 的区别。

执行程序,可以看到,构造函数中,打印出的 geometry 和 frameGeometry 是相同的,这是为什么?

  • 当前代码是放到了构造函数中,此时这个 Widget 对象正在被构造,还没有加入到 window frame 中,因此,此时看不到 window frame 的影响。

如何才能看到二者的影响呢?

  • 添加一个按钮,且生成一个点击信号的槽函数中,由于用户点击的时候,对象已经构造好了,此时 Widget 已经具备了 window frame,因此在位置和尺寸上均出现了差异,代码如下:

如果把上述代码修改成打印 pushButton 的 geometry 和 frameGeometry,结果就是完全相同的,因为 pushButton 并非是一个窗口。

窗口标题:windowTitle

当前 windowTitle 属性,是属于 QWidget 的,只能针对顶层窗口 Widget 才有效,其它的子 Widget,此时是无效的。

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

代码:设置窗口标题

当前不应该给按钮设置窗口标题,但是实际设置了之后,没有任何效果,也没有报错,此时 "没有报错" 这样的设定是不太科学的,这一点,更希望当写出不科学代码的时候,能够给一些报错提示。

窗口图标:windowIcon

windowIcon:表示窗口图标,类似于 windowTitle,只能针对顶层窗口使用,如果对窗口中的控件使用的话,是没有效果的,如下图标:

API 说明
windowlcon() 获取控件的窗口图标,返回 Qlcon 对象
setWindowTitle() 设置控件的窗口图标

代码:设置窗口图标

  • 之前推荐使用堆来创建对象,主要是因为要确保当前控件的生命周期是足够的,要通过 Qt 对象树来释放对象。
  • QIcon 自身是一个比较小的对象,创建出来后,就是要设置到某个 QWidget 里面,QIcon 本身是否释放,不影响图标最终的显示。QIcon 也不支持对象树,无法给他指定父对象。
  • Qt 封装的这些类,都会有同名的头文件。

于此同时,程序在任务栏中的图表也发生改变,如下:

路径相关的使用:

  • 路径不要带有中文。
  • 使用 '/' 作为路径分隔符,是否可以使用 '\' 作为路径分隔符呢?
    • '\' 是转义字符,它搭配一个字符,会存在一些特殊的含义,例如:'\r' 是回车符。
    • C++ 11 引入了 raw string 解决了上述问题,字符串里不包含任何转义字符,也就是所有的字符都不会转移,"d:\rose.png" 也可以是一个完整的路径。
    • 但是我们更推荐使用 '/' 充当路径分隔符。
  • 通过绝对路径的方式引入图片是不科学的。
    • 你写的程序,最终是要发布到用户的电脑上的,你无法确保,你开发机上的图片的路径和用户电脑上的图片的路径完全一致。
      • 比如:我们开发的程序是把图片放到 D 盘上,但是用户的电脑上没有 D 盘,此时就找不到图片。
  • 因此,使用相对路径的方式,使用相对路径是更好的。
    • 相对路径:是以给点目录为基准,以 . 或者 .. 的方式开头。
    • 假设基准目录是 D:/
      • 给定相对路径是 ./rose.png:在基准目录 D:/ 中直接查找 rose.png
      • 给定相对路径是 ./image/rose.png:在基准目录 D:/ 中,先进入 image 目录,再直接查找 rose.png

qrc 机制

万一用户不小心把图片资源删除了,如何办呢?

  • qrc 机制可以从根本上,解决以下问题:
    • 确保你的图片所在的路径在目标用户的机器上存在。
    • 确保你的图片不会被用户搞没了。

qrc 机制介绍:

  • qrc 文件是一种 XML 格式的资源配置文件 (后缀名使用 .qrc 表示),它用 XML 记录硬盘上的文件和对应的随意指定的资源名称,应用程序通过资源名称来访问这些资源。
  • 在 Qt 开发中,可以通过将资源文件添加到项目中来方便地访问和管理这些资源,这些资源文件可以位于 qrc 文件所在目录的同级或其子目录下。
  • Qt 在编译项目的时候,就会根据 qrc 中描述的图片信息,找到图片内容,并且提取出图片的二进制数据,把这些二进制数据转换成 C++ 代码,最终编译到 exe 里面,从而使依赖的资源变得 "与路径无关"。
  • qrc 缺点:无法导入太大的资源文件。
    • 比如:搞几个 GB 这种视频文件,就不太合适了,qrc 无能为力。
    • 这种资源管理机制并非 Qt 独有,很多开发框架都有类似的机制。例如 Android 的 Resources 和 AssetManager 也是类似的效果。

qrc 使用方式

在项目中创建一个 qrc 文件,文件名不要带中文和特殊符号:

把图片导入到 qrc 文件中:

  • 点击 Add Prefix 先创建一个 "前缀",把 前缀的名字修改为 / 即可,如下:

    • 所谓的 "前缀" 可以理解为虚拟的目录,这个目录在你的电脑上不是真实存在,为了方便 Qt 代码访问到这个图片,它是 Qt 自己抽象出来的。
    • qrc 机制本质就是把图片的二进制数据,转换成 C++ 代码,最终就会在代码中看到很大的 char 数组,里面就是图片的二进制数据。
  • 把图片 rose.png 导入到资源文件中,也就是点击 Add Files

    • Add Files 这个按钮在创建 Prefix 之前是禁用的,创建好 Prefix 之后就可以使用了,添加的文件就是添加到 Prefix 下面。
    • 点击 Add Files 得到的目录,就是当前代码所在的目录。
    • 导入图片的时候,需要确保你导入的图片必须在 resource.qrc 文件的同级目录,或者同级目录中的子目录里面。
    • 因此就可以把 rose.png 拷贝到当前项目中即可,再选中 rose.png 导入进来即可。
    • 看到这个效果就说明导入成功了。
    • 当我们代码中需要访问 qrc 中管理文件的时候,就需要在路径中带有 冒号前缀,创建的前缀叫啥名字,代码中就写啥名字。
    • qrc 导入的图片资源,就会自动转换成 qrc_resource.cpp 文件,这里的字节内容就是 rose.png 里的每个字节的数据,内容如下:
    • 当 Qt 项目进行编译的时候,这个 .cpp 文件就一起编译到了 exe 中,当 exe 程序运行的时候,图片的数据也就加载到内存中了。

窗口不透明度:windowOpacity

API 说明
windowOpacity() 获取控件的不透明数值,返回 float,取值为0.1~1.0,其中0.0表示全透明,1.0表示完全不透明
setWindowOpacity() 设置控件的不透明数值

代码:调整窗口透明度

在界面上拖放两个按钮,分别用来增加不透明度和减少不透明度 objectName 分别是 pushButton_add 和 pushButton_sub:

编写 wdiget.cpp,编写两个按钮的 slot 函数:

  • 点击 pushButton_sub 会减少不透明度,也就是窗口越来越透明。
  • 点击 pushButton_add 会增加不透明度,窗口会逐渐恢复。

两个问题:

  • 窗口的不透明度,变化并非是精确的。
    • 整数在内存中的存储。
      • 原码反码补码,字节序。
    • 浮点数在内存中的存储。
      • 遵守 IEEE 754 标准,使用二进制科学计数法的方式。
      • 优点:运算速度快,占用空间小 (CPU 制造的时候,针对这种运算专门优化的)
      • 缺点:对于一些小数无法精确表示。
        • 平时写代码的时候,千万不要把两个浮点数直接使用,例如:0.1+0.2==0.3,这样是错误的,正确写法是:作差,判定差的绝对值小于预期的误差范围。
        • 后续工作中编写代码的时候,尤其是涉及到一个需要精确计算的场景,比如:算钱,一定要慎重使用 float 和 double!
  • 上述代码中,在进行设置之前,先判定 opacity 的范围,然后再决定是否要设置,这个判定其实是可以不写的 (setWindoeOpacity 内部进行了判定),为什么我们要写上?
    • "防御性编程":很多写代码的时候,往往是把一个大的项目分成几个模块,有不同的人去完成,模块之间要进行交互,往往一个模块的 API 要给另一个模块调用。
      • 你在使用别人提供的 API 来进行调用的时候,你是否要对传入的参数进行检查呢?
      • 比如你要传入一个实参,你也不知道这个参数是否是一个 nullptr,是否应该在调用函数之前,先进行判空,还是 API 内部已经进行了判空,你不再需要判空,这是不知道的。
      • 最好的办法就是,在调用 API 之前进行判空,可以做到即便 API 没有进行判空操作,问题也不大。

光标:cursor

API 说明
cursor() 获取控件的光标形状,返回 QCursor 对象
setCursor() 设置控件的光标形状,当鼠标停留在该控件上,就会显示出对应的形状
QGuiApplication::setOverrideCursor() 设置全局光标的形状,对整个程序中的所有控件都会生效,覆盖上main的 setCursor 设置的内容
  • 同一个界面中,不同的控件可以设置成不同的光标。
  • 这里的设置全局光标,是程序内的全局,而不是系统级别的全局。

代码:在 Qt Designer 中设置按钮的光标

截图无法看到光标,运行程序,鼠标悬停到按钮上,即可看到光标会变成一个打开手势。

代码:通过代码设置按钮的光标

运行程序,鼠标悬停到按钮上,即可看到光标会变成一个 "转圈圈的状态"。

Ctrl + 左键点击 Qt::WaitCursor 跳转到源码,即可看到系统内置的光标形状如下:

代码:自定义鼠标光标

Qt 自带的光标形状有限,我们也可以自己找个图片,做成鼠标的光标,这里使用了一个滑稽。

  • 创建 qrc 资源文件,添加前缀 /,并加入 funny.png



  • 编写 widget.cpp,在代码中访问到这个图片,先构造图片对象 (QPixmap),再基于这个图片对象构造出光标对象 (QCursor)
  • pixmap = pixmap.scaled(50, 50):通过这个函数对图片进行缩放,但是缩放并不是修改图片本身,而是返回一个新的图片对象副本。
  • QCursor cursor(pixmap, 10, 10):默认情况下,鼠标点击是,相当于图片的左上角在进行点击,加上该代码的意思是,一图片左上角为 (0, 0) 原点,找到 (10, 10) 这个位置作为鼠标真正点击的位置。
  • 免费的图标获取网站:阿里巴巴矢量图标库 https://www.iconfont.cn/

字体:font

API 说明
font() 获取当前 Widget 的字体信息,返回 QFont 对象
setFont() 设置当前 Widget 的字体信息

关于 QFont

属性 说明
family 字体家族,比如:"楷体"、"宋体"、"微软雅黑" 等
pointSize 字体大小
weight 字体粗细,以数值方式表示粗细程度取值范围 [0, 99],数值越大,越粗
bold 是否加粗,设置为 true 相当于 weight 为 75,设置为 false 相当于 weight 为 50
italic 是否倾斜
underline 是否带有下划线
strikeOut 是否带有删除线

上述属性具体怎么设置,实际开发中,往往有专门的 美工/设计/UED 来进行确定。

  • 但是如果是一些小公司,没有美工,甚至没有产品经理,这个情况,我们作为一个程序员,就可以参考一下别人的程序是怎么安排的,或者别人写的网页时怎么安排的。

代码:在 Qt Designer 中设置字体属性

在界面上创建一个 label 控件,在右侧的属性编辑区,设置该 label 的 font 相关属性。

  • 在 Qt Designer 调整上述属性,可以实时的看到文字的变化。
  • 通过属性编辑这样的方式,虽然能够快速方便的修改文字相关的属性,但是还是不够灵活,如果程序运行过程中,需要修改文字的属性,就需要通过代码来操作了。

代码:在代码中设置字体属性

工具提示:toolTip

一个 GUI 程序,界面比较复杂,按钮啥的很多,当你把鼠标悬停在这个控件上的时候,就能弹出一个提示。

API 说明
setToolTip() 设置 toolTip,鼠标悬停在该 Widget 上时会有提示说明
setToolTipDuring() 设置 toolTip 提示的事件,单位 ms,时间到后 toolTip 自动消失

注意:toolTip 只是给用户看的,在代码中一般不需要获取到 toolTip

代码:设置按钮的 toolTip

在界面上拖放两个按钮,objectName 设置为 pushButton_yes 和 pushButton_no,如下图:

编写 widget.cpp 文件,运行程序后,可以看到鼠标停到按钮上之后,就能弹出提示,时间到后自动消失,如下图:

焦点策略:focusPolicy

设置控件获取到焦点的策略,比如某个控件能否用鼠标选中或者能否通过 tab 键选中。

  • 所谓 "焦点",指的就是能选中这个元素,接下来的操作 (比如键盘操作),就都是针对该焦点元素进行的了,这个对于 输入框,单选框,复选框等控件非常有用的。
  • GUI 中,窗口/控件,焦点是非常关键的。
    • 线上笔试、笔试链接,点击链接,打开一个网站,就可以在线做题了,你在人家的网页中去做题,网页是属于时钟获取到焦点的状态的,你一旦切换到百度/其他程序 (VS) 时,立刻人家的网页就能感知到 "失去焦点",服务器就能收集到你这样的动作,从而衡量你是否涉嫌作弊。
    • 这些线上笔试平台,反作弊机制非常成熟,例如:牛客、赛码;即便是得分低,也有可能通过笔试,一旦作弊,一定通过不了笔试的,甚至可能被公司拉黑。
API 说明
focusPolicy() 获取该 widget 的 focusPolicy,返回 Qt::FocusPolicy
setFocusPolicy() 设置 widget 的 focusPolicy

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

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

代码:理解不同的 focusPolicy

在界面上创建四个单行输入框 (Line Edit),修改四个输入框的 focusPolicy 属性为 Qt::StrongFocus (默认取值,一般不用额外修改),如下图:

此时运行程序后可以看到,使用鼠标单击/tab,就可以移动光标所在输入框,从而接下来的输入就是针对这个获取焦点的输入框展开的了。

  • 修改第二个输⼊框的 focusPolicy 为 Qt::NoFocus,则第二个输入框不会被 tab / 鼠标左键选中,此时这个输入框也就无法输入内容了。

  • 修改第二个输入框 focusPolicy 为 Qt::TabFocus,则只能通过 tab 选中,无法通过鼠标选中。

  • 修改第二个输入框 focusPolicy 为 Qt::ClickFocus,则只能通过 鼠标 选中,无法通过 tab 选中。

样式表:styleSheet

通过 CSS 设置 Widget 的样式。

  • 层叠样式表 (CSS):在进行网页前端开发的时候,设置了网页样式的方式。
    • CSS 这个东西发展了多年,已经非常成熟了,能够提供非常丰富的功能,把网页能设置成非常好看。
  • 样式:描述了界面具体是什么样子的,包括但不限于大小、位置、颜色、间距、字体、背景、边框等。
    • 我们平常看到的丰富多彩的网页,都会大量使用到 CSS
  • Qt 虽然是做 GUI 开发,但是实际上和网页前端有很多异曲同工之妙,因此 Qt 就把 CSS 参考过来了,搞了一套 QSS,虽然相比于 CSS 功能上缺失很多,即使如此也能够帮我们完成不少效果。

代码:设置文本样式

在界面上创建 Label,编辑右侧的 styleSheet 属性,点击三个点,如下:

开始设置样式,效果如下图:

  • 和 CSS 类似,QSS 设置的样式也是 "键值对" 的格式,键和值之间用 冒号 分隔,键值对和键值对之间用 封号 分隔。
  • 具体怎么设置,可以在 Qt 文档中,搜索 QtStyleSheet

代码:通过代码来设置样式,实现一个 "夜间模式" 功能

  • 日间模式:文字是黑色,背景是白色。
  • 夜间模式:文字是白色,背景是黑色。

在界面上创建一个多行输入框 (TextEdit) 和两个按钮,objectName 分别为 pushButton_light 和 pushButton_dark,如下:

右击两个按钮,点击 "转到槽",自动生成点击按钮信号的槽函数,编写代码实现 "日夜切换",如下:

千万要注意这里的单词拼写,不要出错,否则不会有任何报错,但是样式不会失效。

运行代码,向输入框中输入一些文字,如下:

点击两个按钮,效果如下:

如何获取具体的颜色 RGB 呢?可以使用 QQ 截图的功能,如下:

三. QWidget 属性小结

下列表格列出了 QWidget 中的属性及其作用:

相关推荐
万少2 分钟前
HarmonyOS Next 弹窗系列教程(3)
前端·harmonyos·客户端
甜甜的资料库3 分钟前
基于微信小程序的车位共享平台的设计与实现源码数据库文档
数据库·微信小程序·小程序
七灵微1 小时前
【后端】单点登录
服务器·前端
持久的棒棒君5 小时前
npm安装electron下载太慢,导致报错
前端·electron·npm
why1516 小时前
微服务商城-商品微服务
数据库·后端·golang
柒间7 小时前
Elasticsearch 常用操作命令整合 (cURL 版本)
大数据·数据库·elasticsearch
crary,记忆7 小时前
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
前端·webpack·angular·angular.js
漂流瓶jz8 小时前
让数据"流动"起来!Node.js实现流式渲染/流式传输与背后的HTTP原理
前端·javascript·node.js
SamHou08 小时前
手把手 CSS 盒子模型——从零开始的奶奶级 Web 开发教程2
前端·css·web
我不吃饼干8 小时前
从 Vue3 源码中了解你所不知道的 never
前端·typescript