Qt常用控件(一)

一、控件概述

Widget 是 Qt 中的核心概念. 英文原义是 "小部件", 我们此处也把它翻译为 "控件" .

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

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

在Qt中已经给我们提供了很多的"控件",我们就需要学习和了解这些控件,学会如何使用这些控件。

如上,在Qt Designer左侧的这一长条,就是Qt给我们已经内置好的控件了。

Qt中的各种控件都是继承自QWidget类,

二、enabled属性

enabled:描述一个控件是否处于"可用状态",相对的概念就是"禁用"。所谓的"禁用"指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。如果一个widget被禁用了,则该widget的子元素也被禁用。

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

举个例子:

执行上述的代码,我们发现这个创建的按钮变成了灰色,这就是被禁用了。有的人就提出了问题:是不是没连接槽函数导致这个按钮执行不了呢?

我们发现连接了槽函数依旧是灰色的按钮。

三、geometry属性

位置和尺寸,其实是四个属性的统称:x是横坐标,y是纵坐标,width是宽度,heigth是高度。

在实际开发中,我们通常不会直接操作这些属性,而是通过封装的方法来进行获取和修改。

Qt 采用左手坐标系系统,坐标系原点位于当前元素父元素的左上角。

API 说明
geometry() 获取控件的位置和尺寸信息。返回结果为QRect对象,包含x坐标、y坐标、宽度和高度值。其中x和y表示控件左上角的坐标位置。
setGeometry(QRect)setGeometry(int x, int y,int width, int height) 调整控件的位置和尺寸。您可以通过设置QRect对象整体定义,也可以分别设置其四个属性(x、y、width、height)进行精细调整。

QPoint表示一个点,QRect表示一个矩形。它们都属于小对象,里面的属性非常少,占用空间也小。C++中使用上述对象,通常就会按照值的方式来传递参数。

我们在之前的文章中也提到一个move,它只是用来修改位置的。而setGeometry则是既可以修改位置,也可以修改尺寸。

样例:

如上设置出五个按钮,我们期望通过点击下面的四个按钮,就能够修改target按钮的geometry。

编写对应按钮的槽函数:

运行代码:

target按钮的位置就被改变了,但是我们发现改变的很奇怪,这个改变是在调整左上角位置,左上角位置改变的同时,高度和宽度也同样发生了改变。

刚刚我们这个代码,修改的是QRect对象的x和y,这样的修改就会使QRect宽度和高度发生改变。

如果我们想要让这个按钮能够平移(宽度和高度不变,整个按钮的位置都发生改变)该怎么实现呢?

答案是:不再修改QRect,而是通过QRect基于setGeometry第二个版本的函数重新设置位置即可

运行代码:

如上我们就成功的平移target了。

我们再来一个样例,这个样例是找同学请吃饭:

创建一个文本,和两个按钮:

如上运行代码:

点击拒绝按钮后我们会发现一个问题,就是我们点击(按下,起来后)按钮才会改变,那我们能不能在按下的时候按钮的位置就改变呢?

右键按钮,点击转到槽函数后,将信号设成pressed。

将代码改成如下:

四、window frame的影响

看下图

在Qt中,关于位置尺寸,提供了很多API。有的API的位置信息是以Widget本体左上角为原点的(不考虑window frame),有的API的位置信息是以window frame左上角为原点的。

当 widget 作为窗口(包含标题栏、最小化、最大化、关闭按钮)时,尺寸和坐标计算存在两种方式:包含窗口边框和不包含窗口边框。

以下方法采用包含窗口边框的计算方式:x()、y()、

frameGeometry()、pos()、move()

以下方法采用不包含窗口边框的计算方式:geometry()、width()、height()、rect()、size()

需要注意的是,对于非窗口形式的 widget,这两种计算方式得到的结果是一致的。

代码示例: 感受 geometry 和 frameGeometry 的区别

如上我们运行了代码,但是发现它们输出的结果是一样的啊?!这是怎么回事?

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

修改上述代码:

五、windowTitle

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

代码样例:

cpp 复制代码
Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
 {
 ui->setupUi(this);

 // 设置窗⼝标题
 this->setWindowTitle("这是标题");
 }

上面的代码就不给出运行结果了。

六、windowlcon的属性

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

这两个API类似于windowTitle只能针对顶层窗口使用。

Qt把各种涉及到的相关概念,都封装成了类,Qlcon就表示一个图标。

代码样例:

cpp 复制代码
#include <QIcon>
Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
 ui->setupUi(this);
 // 创建图标对象
 QIcon icon("d:/rose.jpg");
 // 设置图标
 this->setWindowIcon(icon);
}

之前推荐使用堆创建对象,主要是因为要确保当前的控件的生命周期是足够的,要通过Qt对象树来释放对象。Qlcon自身是一个比较小的对象,创建出来之后,就是要设置到某个QWidget里面,Qlcon对象本身释放不释放都不影响图标最终的显示,Qlcon也不支持对象树,无法给他执行父对象。

代码运行结果:

我们上述的代码是通过绝对路径的方式引入图片的,这样是不科学的。你写的程序最终是要发布到用户的电脑上的,你无法确保,你开发机上的图片路径和用户电脑上的图片路径完全一致。因此,相比于使用绝对路径,使用相对路径是更好的。

qrc机制:

这个机制就是从根本上解决上述的问题:

1、确保你的图片所在路径在目标用户机器上存在

2、确保你的图片不会被用户搞没

给Qt项目引入一个额外的xml文件(后缀名使用.qrc表示),在这个xml中把要使用的图片资源给导入进来,并且在xml中进行记录,Qt在编译项目的时候,就会根据qrc中描述的图片信息,找到图片内容,并且提取出图片的二进制数据,把这些二进制数据转成C++代码,最终编译到exe中。

qrc缺点:无法导入太大的资源文件

qrc的使用方式:

首先,在项目创建一个qrc文件,文件名不能带有中文和其他特殊符号

第二步:把图片导入qrc文件中

创建一个"前缀",所谓的"前缀"可以理解成虚拟目录,这个目录没有在你的电脑上真实存在,是Qt自己抽象出来的。

qrc机制本质上就是图片的二进制数据转化成C++(最终就会在代码中看到很大的char数组,里面就是图片的二进制数据),为了方便Qt代码中访问到这个图片,Qt就自己抽象出了虚拟目录。

把刚刚使用的图片导入到资源文件中,上述的按钮在创建prefix之前是禁用的,创建好了之后就可以使用了,添加文件就是添加到prefix下面的。注意导入图片的时候,需要确保你导入的图片必须在resource.qrc文件的同级目录下,或者是同级目录中的子目录里。

出现这样的效果就是导入成功了。

七、windowOpacity的属性

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

代码示例:

首先创建两个按钮

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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

void Widget::on_pushButton_add_clicked()
{
    float opacity = this->windowOpacity();
    if(opacity > 1.0)   return;
    qDebug() << opacity;
    opacity += 0.1;
    this->setWindowOpacity(opacity);
}

void Widget::on_pushButton_sub_clicked()
{
    float opacity = this->windowOpacity();
    if(opacity > 1.0)   return;
    qDebug() << opacity;
    opacity -= 0.1;
    this->setWindowOpacity(opacity);
}

运行结果:

打印结果:

上述代码中,在进行设置之前,先判定了opacity的范围,然后再决定是否要设置,这个判断其实可以不写。超过1.0的数字设置不进去,因为setWindowOpacity内部也进行了判定。

八、cursor的属性

API 说明
cursor() 获取当前控件的 cursor 属性,该属性返回一个 QCursor 对象。当鼠标悬停在该控件上时,将显示对应的光标形状。
setCursor(const QCursor& cursor) 设置该 widget 光标的形状. 仅在鼠标停留在该 widget 上时生效
QGuiApplication::setOverrideCursor(const QCursor& cursor) 全局设置光标形状。该设置会影响程序中的所有控件,并会覆盖之前通过 setCursor 方法设置的样式。

样例:

当光标划到按钮内,光标就会变成沙漏的等待状态。

以下是Qt中内置的光标形状:

除了上述的内置形状的光标,Qt允许我们通过自定义的图片来设置光标。

首先我们准备一张图片,把这个图片导入到项目中(qrc管理),在代码中访问到这个图片,基于这个图片构造出光标对象并设置。

再如下,代码

划红部分:这是热点所在的位置,以图片左上角为0,0原点,找到10,10这个位置作为鼠标真正的点击的位置。

如果运行上述代码发现光标很大或者很小,则可以添加下列代码:

通过这个函数对图片进行缩放。注意缩放不是修改图片本身,而是返回一个新的图片对象副本。

九、font的属性

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

关于QFont

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

代码样例:

cpp 复制代码
Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
 ui->setupUi(this);
 // 设置 label 的⽂本内容
 ui->label->setText("这是⼀段⽂本");
 // 创建字体对象
 QFont font;
 // 设置字体家族
 font.setFamily("仿宋");
 // 设置字体⼤⼩
 font.setPointSize(20);
 // 设置字体加粗
 font.setBold(true);
 // 设置字体倾斜
 font.setItalic(true);
 // 设置字体下划线
 font.setUnderline(true);
 // 设置字体删除线
 font.setStrikeOut(true);
 // 设置字体对象到 label 上
 ui->label->setFont(font);
}

运行结果:

十、toolTip的属性

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

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

代码样例:

创建两个按钮

加入下列代码:

cpp 复制代码
Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
 ui->setupUi(this);
 ui->pushButton_yes->setToolTip("这个是 yes 按钮");
 ui->pushButton_yes->setToolTipDuration(3000);
 ui->pushButton_no->setToolTip("这个是 no 按钮");
 ui->pushButton_no->setToolTipDuration(10000);
}

运行结果:

十一、focusPolicy的属性

设置控件获取焦点的策略,例如控制控件是否支持鼠标选中或通过Tab键切换选中。

"焦点"指的是当前被选中的元素。获得焦点后,所有后续操作(如键盘输入)都将作用于该元素。这一特性对输入框、单选按钮、复选框等控件尤为重要。

这就像在《魔兽争霸3》或《星际争霸2》中,需要先选中单位才能对其下达指令一样。

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:在 StrongFocus 基础上增加鼠标滚轮获取焦点功能(新增选项,使用频率较低)

十二、styleSheet的属性

通过 CSS 设置 widget 的样式

CSS(层叠样式表)是一种网页前端技术,主要用于定义界面样式。

所谓"样式"包含但不限于以下元素:尺寸和位置、颜色和间距、字体和背景、边框效果

我们日常浏览的丰富多彩的网页,都大量运用了CSS技术。

虽然Qt主要用于GUI开发,但其与网页前端技术存在诸多相似之处。因此Qt框架也提供了对CSS的支持。

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

代码样例:

创建一个label(在右侧我们可以看到styleSheet的设置):

点击它会有一个按钮,再点击会出现一个输入框。或者是右键点击label,然后点击改变样式表也会出现这个输入框

我们设置样式,这里注意,和CSS类似,QSS设置样式也是键值对的格式。键和值之间使用:分隔,键值对和键值对之间使用;分隔

点击确定后

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

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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


void Widget::on_pushButton_light_clicked()
{
    //设置窗口样式
    this->setStyleSheet("background-color: white;");
    //设置输入框样式
    ui->textEdit->setStyleSheet("background-color: white; color: black;");
    //设置按钮样式
    ui->pushButton_light->setStyleSheet("color: black;");
    ui->pushButton_dark->setStyleSheet("color: black;");
}

void Widget::on_pushButton_dark_clicked()
{
    //设置窗口样式
    this->setStyleSheet("background-color: black;");
    //设置输入框样式
    ui->textEdit->setStyleSheet("background-color: black; color: white;");
    //设置按钮样式
    ui->pushButton_light->setStyleSheet("color: white;");
    ui->pushButton_dark->setStyleSheet("color: white;");
}

运行代码:

咋一看,感觉对了,但是有没有发现这个日间模式怎么那么奇怪啊?

正常不应该是这样的吗?难道是代码出错了吗?

其实不是代码的问题,我们需要了解计算机中,使用RGB的方式来表示颜色。

举个例子,表示一个颜色:

  1. rgb(255, 0, 255) 前者表示红色拉满,中间表示绿色拉满,后者表示蓝色拉满。
  2. #FF00FF 前者表示红色拉满,中间表示绿色拉满,后者表示蓝色拉满

那我们怎么知道刚刚日间模式那个白色是怎么组成的能?我们可以用QQ截图,里面内置了一个取色器。

如图就完成了上述的程序。

相关推荐
被AI抢饭碗的人2 小时前
linux:进程间通信
linux·运维·服务器
小尧嵌入式3 小时前
QT软件开发知识点流程及图片转换工具的开发
开发语言·arm开发·qt
weixin_46683 小时前
Docker Dockerfile文件
linux·运维·服务器
保持低旋律节奏3 小时前
linux——软件包、yum 安装和卸载
linux·运维·服务器
深圳市恒讯科技3 小时前
美国服务器备份策略:快照、异地备份与恢复演练指南
运维·服务器·github
翼龙云_cloud3 小时前
阿里云渠道商:无影云电脑怎么使用?
运维·服务器·阿里云·云计算·电脑
AI科技星4 小时前
时空运动的几何约束:张祥前统一场论中圆柱螺旋运动光速不变性的严格数学证明与物理诠释
服务器·数据结构·人工智能·python·科技·算法·生活
天涯路s4 小时前
qt怎么将模块注册成插件
java·服务器·前端·qt
LFly_ice4 小时前
LINQ语法
服务器·solr·linq