当前位置: 首页 > article >正文

[Qt] 常用控件 | QWidget | “表白程序2.0”

目录

一、控件概述

控件体系的发展阶段:

二、QWidget 核心属性

核心属性概览:

1、enabled

2、Geometry

实例 1: 控制按钮的位置

实例 2: 表白 程序

i、Window Frame 的影响

ii、API 设计理念

iii、Geometry 和 FrameGeometry 的区别

(1) 在按钮的 slot 函数中编写代码 & 在构造函数中也添加同样的代码

(2)执行程序


一、控件概述

  • Widget:Qt 中的核心概念,指图形化界面的基本构成元素(如按钮、列表视图等),即“控件”。
  • Qt 的优势:内置大量常用控件,并支持自定义控件,便于快速开发符合需求的界面。

像上述示例中的按钮列表视图树形视图单行输入框多行输入框滚动条下拉框都可以称为控件”。

  • Qt 作为一个成熟的 GUI 开发框架,内置了大量的常用控件。
  • 这一点在 Qt Designer 中就可以看出来,并且 Qt 也提供了 “自定义控件” 的能力,可以让我们在现有控件不能满足需求的时候,对现有控件做出扩展,或者手搓出新的控件。

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


控件体系的发展阶段:
  1. 无控件阶段完全没有控件。此时需要通过一些绘图 API 手动的绘制出按钮或者输入框等内容,代码编写繁琐。

(例如文曲星的 Lava 平台开发)

  1. 粗略控件阶段提供基本控件,如按钮和输入框,简化了GUI开发。

(例如 html 的原生控件)

  1. 成熟控件体系更完整的控件体系,基本可以覆盖到 GUI 开发中的大部分场景。(例如早期的 MFC、VB、C++ Builder、Qt、Delphi、后来的 Android SDK、Java FX、前端的各种 UI 库等)

上图是前端中的 Element-ui 中的控件概览,无论是丰富程度还是颜值,都比 Qt 自带的控件更胜一筹


二、QWidget 核心属性

  • 在 Qt 中,使用 QWidget 类表示 “控件”,像按钮、视图、输入框、滚动条等具体的控件类,都是继承自 QWidget。QWidget 中包含了 Qt 整个控件体系中通用的部分。
  • 在 Qt Designer 中,随便拖一个控件过来,选中该控件,即可在右下方可以看到 QWidget 中的属性。

这些属性既可以通过 QtDesigner 直接修改,也可以通过代码的方式修改。这些属性的具体含义在 Qt Assistant 中均有详细介绍。

Qt Assistant 中搜索 QWidget,即可找到对应的文档说明(或者在 Qt Creator 代码中选中 QWidget,按 F1(+Fn) 也可)


核心属性概览:

QWidget 属性及其作用:

属性

作⽤

enabled

设置控件是否可使用。true 表示可用,false 表示禁用。

geometry

控制控件的位置和尺寸,包含 x, y, width, height 四个部分。坐标是以父元素为参考进行设置的。

windowTitle

设置 widget 的标题。

windowIcon

设置 widget 的图标。

windowOpacity

设置 widget 的透明度。

cursor

设置鼠标悬停时显示的图标形状,如普通箭头、沙漏或十字等。可通过 Qt Designer 查看选项。

font

控制字体相关属性,包括字体家族、大小、粗体、斜体、下划线等样式。

toolTip

当鼠标悬停在 widget 上时,在状态栏中显示的提示信息。

toolTipDuration

toolTip 显示的持续时间。

statusTip

当 widget 状态发生改变时(如按钮被按下)显示的提示信息。

whatsThis

当鼠标悬停并按下 Alt+F1 时,显示的帮助信息(显示在一个弹出窗口中)。

styleSheet

允许使用 CSS 来设置 widget 中的样式,支持丰富的样式,便于前端开发者上手。

focusPolicy

定义 widget 如何获取焦点:NoFocus, TabFocus, ClickFocus, StrongFocus, WheelFocus

contextMenuPolicy

设置上下文菜单的显示策略:DefaultContextMenu, NoContextMenu, PreventContextMenu, ActionsContextMenu, CustomContextMenu

locale

设置语言和国家地区。

acceptDrops

设置该部件是否接受拖放操作。true 表示可以接收来自其他部件的拖放操作;false 则表示不接收任何拖放操作。

minimumSize

控件的最小尺寸,包含最小宽度和最小高度。

maximumSize

控件的最大尺寸,包含最大宽度和最大高度。

sizePolicy

设置控件在布局管理器中的缩放方式。

windowModality

指定窗口是否具有 "模态" 行为。

sizeIncrement

拖动窗口大小时的增量单位。

baseSize

窗口的基础大小,用于配合 sizeIncrement 调整组件尺寸。

palette

设置 widget 的颜色风格。

mouseTracking

是否跟踪鼠标移动事件。true 表示需要跟踪;false 表示不需要跟踪。

tabletTracking

是否跟踪触摸屏的移动事件,类似于 mouseTracking。Qt 5.9 引入的新属性。

layoutDirection

设置布局方向:LeftToRight, RightToLeft, LayoutDirectionAuto

autoFillBackground

是否自动填充背景颜色。

windowFilePath

将 widget 和一个本地文件路径关联起来。

accessibleName

设置 widget 的可访问名称,辅助技术(如屏幕阅读器)可以获取到这个名称。

accessibleDescription

设置 widget 的详细描述,作用同 accessibleName

inputMethodHints

针对输入框有效,用来提示用户当前能输入的合法数据格式,如只能输入数字、只能输入日期等。

下面我会介绍上面列出的其中一些比较重要和常用的属性。


1、enabled

  • 所谓 “禁用” 指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。
  • 如果一个 widget 被禁用,则该 widget 的子元素也被禁用。

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

运行程序,可以看到按钮处于灰色状态,无法被点击:


通过按钮 2 切换按钮 1 的禁用状态

(1)使用 Qt Designer 拖两个按钮到 Widget 中

  • 两个按钮的 objectName 分别为 pushButton 和 pushButton_2。

QObject 的 objectName 属性介绍:

  • QObject 是 QWidget 的父类,里面最主要的属性就是 objectName。在一个 Qt 程序中,objectName 相当于对象的身份标识,彼此之间不能重复。
  • 在使用 Qt Designer 时,尤其是界面上存在多个 widget 的时候,可以通过 objectName 获取到指定的 widget 对象。
  • Qt Designer 生成的 ui 文件,本身是 xml 格式的,qmake 会把这个 xml 文件转换成 C++ 的 .h 文件(这个文件生成在 build 目录中),构成一个 ui_widget 类。
  • 每个 widget 的 objectName 最终就会成为 ui_widget 类的属性名字。最终这个类的实例就是:Ui::Widget *ui,因此就可以通过形如 ui->pushButton 或者 ui->pushButton_2 这样的代码获取到界面上的 widget 对象了。
  • 当前自动生成的 objectName 是有规律的:控件的类型 + 下划线 + 数字。很明显,以数字的方式命名并不是一个好的编程习惯,这里我将它修改为如下所示:

(2)生成两个按钮的 slot 函数

  • 使用 isEnabled 获取当前按钮的可用状态。
  • 使用 setEnabled 修改按钮的可用状态,此处是直接针对原来的可用状态进行取反后设置。

运行程序可以看到:初始情况下,上面的按钮是可用状态。接着点击下方按钮,即可使上方按钮被禁用~

在 Qt Designer 中创建按钮的时候可以设置按钮的初始状态是 “可用” 还是 “禁用”。如果把 enabled 这一列的对钩去掉,则按钮的初始状态就是 “禁用” 状态。


2、Geometry

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

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

在实际开发中,我们通常不会直接使用这四个属性来获取或修改控件的位置和大小。

Qt 提供了一系列封装的方法,这些方法更方便操作,并且考虑到了 Qt 的左手坐标系——其中原点位于父元素的左上角。

实例 1: 控制按钮的位置

创建界面布局:

  • 在界面上拖拽五个按钮,分别命名为 pushButton_target(目标按钮)、pushButton_up(向上移动按钮)、pushButton_down(向下移动按钮)、pushButton_left(向左移动按钮)和 pushButton_right(向右移动按钮)。这些按钮的初始位置和大小可以随意设置。

编写槽函数:

    • widget.cpp 文件中为每个方向的按钮添加槽函数,用于改变 pushButton_target 的位置。当点击相应的方向按钮时,会调整目标按钮的 x 和 y 坐标,从而实现位置变化。
    • 注意,这样做会导致按钮的整个矩形区域发生位移,而不仅仅是其左上角

优化移动逻辑:

    • 如果希望按钮只移动而不改变尺寸,应该避免直接修改 QRect 对象中的 x 和 y 值。
    • 相反,可以通过 setGeometry() 方法的第二个版本来重新设定按钮的位置,保持宽度和高度不变。

上述代码使用 move 方法也是可以的。

运行,发现设置成功~

实例 2: 表白 程序

设计界面:

    • 向界面上添加两个按钮(接受 pushButton_accept 和拒绝 pushButton_reject)以及一个标签 label,用来显示文本信息。

实现交互逻辑:

    • widget.cpp 中定义槽函数,使得当用户点击 "Sorry.." 拒绝按钮时,触发按钮逃跑的行为。
    • 此行为可以通过监听 clicked 事件(即鼠标点击后释放)实现。

运行程序可以看到:当点击 "Sorry.." 时,按钮就跑了。

上述代码使用的是 clicked(一下一上是点击),如果使用 pressed(鼠标按下事件)。

如果使用 mouseMoveEvent,会更狠一些, 只要鼠标移动过来,按钮就跑了

对应的代码更麻烦⼀些,需要使用到 Qt 的使用机制(需要自定义类继承自 QPushButton,重写 mouseMoveEvent 方法)这里就暂时不展开了。


i、Window Frame 的影响

widget 作为一个窗口时(例如带有标题栏等),计算尺寸和坐标有两种算法:

  • 包含 window frame 的方式(如 x(), y(), frameGeometry(), pos(), move()
  • 不包含 window frame 的方式(如 geometry(), width(), height(), rect(), size()

对于非窗口的 widget,这两种计算方式的结果是一致的。

ii、API 设计理念

API

说明

x()

获取横坐标。计算时包含 window frame。

y()

获取纵坐标。计算时包含 window frame。

pos()

返回 QPoint 对象,包含 x()y() 的值及设置方法。计算时包含 window frame。

frameSize()

返回 QSize 对象,包含 width()height() 及其设置方法。计算时包含 window frame。

frameGeometry()

返回 QRect 对象,相当于 QPointQSize 的结合体,可以获取 x, y, width, size。计算时包含 window frame 对象。

width()

获取宽度。计算时不包含 window frame。

height()

获取高度。计算时不包含 window frame。

size()

返回 QSize 对象,包含 width()height() 及其设置方法。计算时不包含 window frame。

rect()

返回 QRect 对象,可以获取并设置 x, y, width, size。计算时不包含 window frame 对象。

geometry()

返回 QRect 对象,可以获取 x, y, width, size。计算时不包含 window frame 对象。

setGeometry()

设置窗口的位置和尺寸,可以设置 x, y, width, height 或 QRect 对象。计算时不包含 window frame 对象。

认真观察上面的表格,可以看到,其实这里的 API 有 frameGeometry 和 geometry 两个就足够完成所有的需求了。

为什么要提供这么多功能重复的 API 呢?

这涉及到 Qt API 的设计理念:尽量符合人的直觉。例如,Qt 的 QVector 提供了多种尾插元素的方法:

  • push_back
  • append
  • +=
  • <<

上述方法的效果都是等价的,即使不翻阅文档,单纯的凭借直觉就能把代码写对。减少了记忆负担,使编程变得更加直观和友好。


iii、Geometry 和 FrameGeometry 的区别
(1) 在按钮的 slot 函数中编写代码 & 在构造函数中也添加同样的代码

(2)执行程序
  • 可以看到:在构造函数中打印出的 geometry 和 frameGeometry 是相同的。
  • 但是在点击按钮时,打印的 geometry 和 frameGeometry 则存在差异。

注意:

  • 在构造方法中,Widget 刚刚创建出来,还没有加入到对象树中,此时也就不具备 Window frame。
  • 在按钮的 slot 函数中,由于用户点击的时候,对象树已经构造好了,此时 Widget 已经具备了 Window frame,因此在位置和尺寸上均出现了差异。
  • 如果把上述代码修改成打印 pushButton 的 geometry 和 frameGeometry,结果就是完全相同的。因为 pushButton 并非是一个窗口。

http://www.kler.cn/a/464548.html

相关文章:

  • Linux下编译安装PETSc
  • 图像超分辨新SOTA!南洋理工提出InvSR,利用大型预训练扩散模型图像先验来提高 SR 性能, 登上Huggingface热门项目。
  • 三、GIT与Github推送(上传)和克隆(下载)
  • Redis的缓存雪崩,缓存击穿,缓存穿透
  • 代码随想录算法训练营第五十天|图论基础|深度优先搜索理论基础|KM98.所有可达路径|广度优先搜索理论基础
  • UniApp 状态管理:Vuex 在 UniApp 中的实践
  • 按字段拆分多个工作表到独立的工作簿并增加合计-Excel易用宝
  • 2024年社区高光时刻总结!
  • 【git】git stash相关指令
  • Spring 中的 @ExceptionHandler 注解详解与应用
  • Docker- Unable to find image “hello-world“locally
  • 去除el-tabs 下面的灰色横线,并修改每一项的左右间距,和字体颜色
  • 无人机快速巡检、森林、电力、水利大大节省人力成本,降低风险事故
  • 【文献精读笔记】Explainability for Large Language Models: A Survey (大语言模型的可解释性综述)(五)
  • GJB软件需求规格说明模板及详解
  • C# 设计模式(创建型模式):单例模式
  • 大型概念模型:在句子表示空间中的语言建模
  • CSS疑难记录
  • 基于通义千问2-VL-7B-Instruct模型的微调技术指南
  • 性能测试中如何设计真实的负载呢?
  • PyTorch快速入门教程【小土堆】之卷积层
  • 每日一些题
  • Excel重新踩坑5:二级下拉列表制作;★数据透视表;
  • C++ 日志库 spdlog 使用教程
  • smell---Paddle-DI
  • U盘提示格式化?原因、恢复方案与预防措施全解析