[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 并非是一个窗口。

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

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

相关文章

GAN对抗生成网络(二)——算法及Python实现

1 算法步骤 上一篇提到的GAN的最优化问题是&#xff0c;本文记录如何求解这一问题。 首先为了表示方便&#xff0c;记&#xff0c;这里让最大的可视作常量。 第一步&#xff0c;给定初始的&#xff0c;使用梯度上升找到 ,最大化。关于梯度下降&#xff0c;可以参考笔者另一篇…

JAVA(二)【未完】

数据类型与变量 数据类型&#xff1a;基本数据类型&#xff1a;整型&#xff1a;byte short int long 浮点型&#xff1a;float double char 布尔型&#xff1a;boolean 引用数据类型&#xff1a;数组 类 接口 枚举类型 long b 10l;System.out.println(b);System.out.printl…

C语言day5:shell脚本

一、练习题1 定义一个find函数&#xff0c;查找ubuntu和root的gid并使用变量接收结果 二、练习题2 定义一个数组&#xff0c;写一个函数完成对数组的冒泡排序 三、练习题3 使用break求1-100中的质数&#xff08;质数&#xff1a;只能被1和它本身整除&#xff0c;如&#xff1a;…

R语言6种将字符转成数字的方法,写在新年来临之际

咱们临床研究中&#xff0c;拿到数据后首先要对数据进行清洗&#xff0c;把数据变成咱们想要的格式&#xff0c;才能进行下一步分析&#xff0c;其中数据中的字符转成数字是个重要的内容&#xff0c;因为字符中常含有特殊符号&#xff0c;不利于分析&#xff0c;转成数字后才能…

C语言面的向对象编程(OOP)

如果使用过C、C#、Java语言&#xff0c;一定知道面向对象编程&#xff0c;这些语言对面向对象编程的支持是语言级别的。C语言在语言级别不支持面向对象&#xff0c;那可以实现面向对象吗&#xff1f;其实面向对象是一种思想&#xff0c;而不是一种语言&#xff0c;很多初学者很…

C++ 基础思维导图(一)

目录 1、C基础 IO流 namespace 引用、const inline、函数参数 重载 2、类和对象 类举例 3、 内存管理 new/delete 对象内存分布 内存泄漏 4、继承 继承权限 继承中的构造与析构 菱形继承 1、C基础 IO流 #include <iostream> #include <iomanip> //…

聊聊前端框架中的process.env,env的来源及优先级(next.js、vue-cli、vite)

在平时开发中&#xff0c;常常使用vue、react相关脚手架创建项目&#xff0c;在项目根目录可以创建.env、.env.[mode]&#xff08;mode为development、production、test)、.env.local等文件&#xff0c;然后在项目中就可以通过process.env来访问相关的环境变量了。 下面针对如下…

基于云架构Web端的工业MES系统:赋能制造业数字化变革

基于云架构Web端的工业MES系统:赋能制造业数字化变革 在当今数字化浪潮席卷全球的背景下,制造业作为国家经济发展的重要支柱产业,正面临着前所未有的机遇与挑战。市场需求的快速变化、客户个性化定制要求的日益提高以及全球竞争的愈发激烈,都促使制造企业必须寻求更加高效、智…

LeetCode算法题——螺旋矩阵ll

题目描述 给你一个正整数n&#xff0c;生成一个包含1到n2所有元素&#xff0c;且元素按顺时针顺序螺旋排列的n x n正方形矩阵matrix 。 示例 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]题解 思路&#xff1a; 将整个过程分解为逐圈填充的过程&#xf…

MySQL 01 02 章——数据库概述与MySQL安装篇

一、数据库概述 &#xff08;1&#xff09;为什么要使用数据库 数据库可以实现持久化&#xff0c;什么是持久化&#xff1a;数据持久化意味着将内存中的数据保存到硬盘上加以“固化”持久化的主要作用是&#xff1a;将内存中的数据存储在关系型数据库中&#xff0c;当然也可以…

GPU 进阶笔记(四):NVIDIA GH200 芯片、服务器及集群组网

大家读完觉得有意义记得关注和点赞&#xff01;&#xff01;&#xff01; 1 传统原厂 GPU 服务器&#xff1a;Intel/AMD x86 CPU NVIDIA GPU2 新一代原厂 GPU 服务器&#xff1a;NVIDIA CPU NVIDIA GPU 2.1 CPU 芯片&#xff1a;Grace (ARM)2.2 GPU 芯片&#xff1a;Hopper/B…

vite6+vue3+ts+prettier+eslint9配置前端项目(后台管理系统、移动端H5项目通用配置)

很多小伙伴苦于无法搭建一个规范的前端项目&#xff0c;导致后续开发不规范&#xff0c;今天给大家带来一个基于Vite6TypeScriptVue3ESlint9Prettier的搭建教程。 目录 一、基础配置1、初始化项目2、代码质量风格的统一2.1、配置prettier2.2、配置eslint2.3、配置typescript 3、…

ESLint+Prettier的配置

ESLintPrettier的配置 安装插件 ​​​​​​ 在settings.json中写下配置 {// tab自动转换标签"emmet.triggerExpansionOnTab": true,"workbench.colorTheme": "Default Dark","editor.tabSize": 2,"editor.fontSize": …

Cyber Security 101-Web Hacking-JavaScript Essentials(JavaScript 基础)

任务1&#xff1a;介绍 JavaScript &#xff08;JS&#xff09; 是一种流行的脚本语言&#xff0c;它允许 Web 开发人员向包含 HTML 和 CSS&#xff08;样式&#xff09;的网站添加交互式功能。创建 HTML 元素后&#xff0c;您可以通过 JS 添加交互性&#xff0c;例如验证、on…

《机器学习》从入门到实战——逻辑回归

目录 一、简介 二、逻辑回归的原理 1、线性回归部分 2、逻辑函数&#xff08;Sigmoid函数&#xff09; 3、分类决策 4、转换为概率的形式使用似然函数求解 5、对数似然函数 ​编辑 6、转换为梯度下降任务 三、逻辑回归拓展知识 1、数据标准化 &#xff08;1&#xf…

JDK8源码分析Jdk动态代理底层原理

本文侧重分析JDK8中jdk动态代理的源码&#xff0c;若是想看JDK17源码分析可以看我的这一篇文章 JDK17源码分析Jdk动态代理底层原理-CSDN博客 两者之间有着略微的差别&#xff0c;JDK17在JDK8上改进了不少 目录 源码分析 过程 生成的代理类大致结构 本文侧重分析JDK8中jdk…

ZYNQ初识6(zynq_7010)clock时钟IP核

基于板子的PL端无时钟晶振&#xff0c;需要从PS端借用clock1&#xff08;50M&#xff09;晶振 接下去是自定义clock的IP核封装&#xff0c;为后续的simulation可以正常仿真波形&#xff0c;需要注意顶层文件的设置&#xff0c;需要将自定义的IP核对应的.v文件设置为顶层文件&a…

深度学习模型格式转换:pytorch2onnx(包含自定义操作符)

将PyTorch模型转换为ONNX&#xff08;Open Neural Network Exchange&#xff09;格式是实现模型跨平台部署和优化推理性能的一种常见方法。PyTorch 提供了多种方式来完成这一转换&#xff0c;以下是几种主要的方法&#xff1a; 一、静态模型转换 使用 torch.onnx.export() t…

GPU 进阶笔记(一):高性能 GPU 服务器硬件拓扑与集群组网

记录一些平时接触到的 GPU 知识。由于是笔记而非教程&#xff0c;因此内容不求连贯&#xff0c;有基础的同学可作查漏补缺之用 1 术语与基础 1.1 PCIe 交换芯片1.2 NVLink 定义演进&#xff1a;1/2/3/4 代监控1.3 NVSwitch1.4 NVLink Switch1.5 HBM (High Bandwidth Memory) 由…

在Unity中用Ab包加载资源(简单好抄)

第一步创建一个Editor文件夹 第二步编写BuildAb&#xff08;这个脚本一点要放在Editor中因为这是一个编辑器脚本&#xff0c;放在其他地方可能会报错&#xff09; using System.IO; using UnityEditor; using UnityEngine;public class BuildAb : MonoBehaviour {// 在Unity编…