【Qt】常用控件----QWidget属性

目录

前言

书接上文【Qt】信号和槽详情点击查看,今天继续来介绍【Qt】常用控件----QWidget

一、控件概述

  • Widget是Qt中的核心概念。英文原义是"小部件",我们此处也把它翻译为"控件"。控件是构成一个图形化界面的基本要素
  • Qt作为一个成熟的GUI开发框架,内置了大量的常用控件。这一点在Qt Designer中就可以看到端倪。并且Qt也提供了"自定义控件"的能力,可以让程序猿在现有控件不能满足需求的时候,对现有控件做出扩展,或者手搓出新的控件

二、QWidget核心属性

  • 在Qt中,使用QWidget类表示"控件"。像按钮、视图、输入框、滚动条等具体的控件类,都是继承自QWidget,可以说,QWidget中就包含了Qt整个控件体系中通用的部分
  • 在Qt Designer中,随便拖一个控件过来,选中该控件,即可在右下方看到QWidget中的属性,这些属性既可以通过Qt Designer直接修改,也可以通过代码的方式修改。这些属性的具体含义在Qt Assistant中均有详细介绍(在Qt Assistant中搜索QWidget 即可找到对应的文档说明(或者在Qt Creator代码中选中QWidget按F1 也可))

enabled

  • 作用:设置控件是否可使用:true 表示可用,false 表示禁用
  • 所谓"禁用"指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的,如果一个widget被禁用,则该widget的子元素也被禁用
API 说明
isEnabled() 获取到控件的可用状态
setEnabled 设置控件是否可使用。true 表示可用,false 表示禁用
  1. 我们创建一个按钮控件,并当点击按钮之后会打印出handle字样。但是现在我们禁用按钮,查看效果
  • 首先按钮是灰色的,点击按钮并没有任何反应
  1. 我们使用ui文件创建两个按钮,其中一个按钮的功能就是切换另外一个按钮的可用不可用
  • 在同一个界面中,要求不同控件的objectName必须是不同的(不能重复),后续通过ui->objectName方式来获取对应控件对象(ui->pushButton,获得第一个按钮对象;ui->pushButton2,获得第二个按钮对象)


  • 我们可以发现,objectName的自动生成的名字是控件类型+下划线+数字,我们可以根据控件功能修改objectName,如下图:
  • 创建两个按钮的槽函数,按钮1:当按钮可用,点击按钮之后打印日志:执行了槽函数;按钮2:当点击按钮2,则获取按钮1的状态,如果可用,则将状态设置成不可用;如果按钮不可用,则将状态设置成可用

geometry

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

• x:横坐标

• y:纵坐标

• width:宽度

• height:高度

API 说明
geometry() 获取到控件的位置和尺寸,返回结果是⼀个QRect(矩形,QRect.x等来访问x、y...),包含了x、y、width、height。其中x、y是左上角的坐标
setGeometry(QRect)、setGeometry(int x,int y,int width,int height) 设置控件的位置和尺寸,可以直接设置一个QRect,也可以分四个属性单独设置
  1. 一个按钮控制target按钮向上,一个按钮控制target按钮向下,一个按钮控制target按钮向左,一个按钮控制target按钮向右
  • 使用ui文件创建5个按钮,将按钮名字修改为pushButton_target、pushButton_up、pushButton_down、pushButton_left、pushButton_right

  • 分别定义槽函数,运行,我们发现不管怎么点击按钮,target按钮没有变化,因为下面代码中,我们修改的是我们在各个函数内部定义的QRect类型rect局部变量,并没有修改target按钮的

  • 因此我们要将修改后的rect传入到函数setGeometry(rect)

  • 运行代码,点击up按钮发现,target按钮有变化,但是它是y轴变长了,我们想要的是按钮框不变的情况下上下左右移动。当前代码调整的是左上角的位置,同时改变了高度和宽度

  • 因此我们不能通过传入Qrect来修改,而是传入x、y、width、height来修改即可

    运行结果如下:target按钮能移动且不改变宽度和高度

Window Frame

  • 如果widget作为一个窗口(带有标题栏:最小化、最大化、关闭按钮),那么在计算尺寸和坐标的时候就有两种算法:包含window frame和不包含window frame。
  • 其中x()、y()、frameGeometry()、pos()、move()都是按照包含window frame的方式来计算的。
  • 其中geometry()、width()、height()、rect()、size()则是按照不包含window frame的方式来计算的。
  • 当然,如果一个不是作为窗口 的widget,上述两类方式得到的结果是一致的
  1. 验证geometry()和frameGeometry()的区别
  • 从打印日志可以看到两个是完全一样的,这是为什么呢?
  • 我们可以看到geometry()和frameGeometry()是放在构造函数中,Widget刚刚创建出来,还没有加入到对象树中,此时也就不具备Window frame,因此还看不到差异
  • 现在,我们将geometry()和frameGeometry()代码和按钮关联,点击按钮之后再使用geometry()、frameGeometry()
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton* button = new QPushButton(this);
    button->setText("按钮");
    button->move(200, 200);
    connect(button, &QPushButton::clicked, this, &Widget::handleClicked);

}

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

void Widget::handleClicked()
{
        QRect rect1 = this->geometry();
        QRect rect2 = this->frameGeometry();
        qDebug() << rect1;
        qDebug() << rect2;
}

windowTitle

  • windowTitle属性,只针对顶层widget(独立窗口)的Widget才会有效,如果是子widget,这个操作无任何效果
API 说明
windowTitle() 获取到控件的窗口标题
setWindowTitle(const QString& title) 设置控件的窗口标题

从下面运行结果可以看出,顶层Widget设置窗口标题成功,下面子Widget就算设置了窗口标题没有效果,没有报错

windowIcon

  • windowIcon 表示窗口的图标,和windowTitle属性,只针对顶层widget(独立窗口)的Widget才会有效
API 说明
windowIcon() 获取到控件的窗口图标,返回QIcon对象
setWindowIcon(const QIcon& icon) 设置控件的窗口图标
  • windowIcon()很少使用,QIcon表示一个图标
  • Qlcan自身是一个比较小的对象,创建出来后就是要设置到某个QWidget里面,Qlcon本身释放不释放不影响图标最终的显示(Qlcon不支持对象树,无法给它执行父对象),因此我们不需要在堆上申请(new)
  • Windows下路径的分隔符可以使用 / 也可以使用 \ ,但是如果在字符串中使用 \ 需要写作转义字符的形式 \ ,因此我们还是更推荐使用 /
  1. 现在我们实现将窗口图标替换成我们自己的一张图片。先在D盘中放一个图片,名字为Qt.png
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QIcon>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置图标
    QIcon icon("D:/XMind/Qt.png");
    this->setWindowIcon(icon);
}

Widget::~Widget()
{
    delete ui;
}
  • 实际开发中,我们一般不会在代码中通过绝对路径引入图片,因为我们无法保证程序发布后,用户的电脑上也有同样的路径。如果使用相对路径,则需要确保代码中的相对路径写法和图片实际所在的路径匹配(比如代码中写作"./image/Qt.png",就需要在当前工作目录中创建image目录,并把Qt.png放进去)

qrc机制

  • qrc文件是⼀种XML格式(后缀名使用.qrc)的资源配置文件,它用XML记录硬盘上的文件和对应的随意指定的资源名称。应用程序通过资源名称来访问这些资源
  • 在Qt开发中,可以通过将资源文件添加到项目中来方便地访问和管理这些资源。这些资源文件可以位于qrc文件所在目录的同级或其子目录下
  • 在构建程序的过程中,Qt会把资源文件的二进制数据转成cpp代码,编译到exe中。从而使依赖的资源变得"路径无关"(Qt在编译项目的时候,就会根据qrc中描述的图片信息,找到图片内容,并且提取出图片中的二进制数据,把这些二进制数据转换成c++代码最终编译到exe中)

qrc缺点:

  • 无法导入太大的资源文件(比如几个GB的视频文件,qrc不可以)
  • 在上面代码的基础上创建一个qrc文件(文件名不带中文和特殊符号)
    .qrc后缀可加可不加

    创建完成页面如下:
  • 将图片导入到qrc文件中
  1. 在qrc编辑器中,添加前缀(Prefix):前缀设置成 / 即可,所谓前缀可以理解成虚拟目录,这个目录没有在你电脑上真实存在,而是Qt自己抽象出来的(qrc机制的本质就是把图片的二进制数据转化为C++代码,最终就会在代码中看到很大的char数组,里面就是图片的二进制数据)

  2. 将图片导入到资源文件中:资源编辑器中,点击add Files 添加资源文件。此处我们需要添加的是Qt.png)注意:添加的文件必须是在qrc文件的同级目录,或者同级目录的子目录中。因此我们需要把之前D盘中的Qt.png复制到上述目录中

  3. qrc路径的访问规则:

    • 使用: 作为开头表示从qrc中读取资源

    / 是上面配置的前缀

    • Qt.png 是资源的名称

  4. 运行程序

  5. qrc中导入的图片资源会被转换成这个qrc_resource.cpp这个C++代码

  6. .cpp文件中保存的是图片里每一个字节的数据 (当Qt项目进行编译时,这个cpp文件也就被一起编译在exe文件中,当exe程序执行的时候。上述图片数据就被加载到内存之中)

windowOpacity

  • windowOpacity:设置窗口透明度
API 说明
windowOpacity() 获取到控件的不透明数值,返回float----取值为0.0->1.0。其中0.0表示全透明,1.0表示完全不透明
setWindowOpacity(float n) 设置控件的不透明数值
  1. 创建两个按钮,一个按钮增加透明度,一个按钮减少(objectName:pushButton_add、pushButton_sub)
  2. 定义槽函数
cpp 复制代码
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 <= 0.0)
        return;
    qDebug() << opacity;
    opacity -= 0.1;
    this->setWindowOpacity(opacity);
}

按-的按钮,窗口变透明,我们发现打印日志并不是按照每次减0.1来减少的(原因:浮点数在内存中的存储方式)


cursor

API 说明
cursor() 获取到当前widget的cursor属性,返回QCursor对象。当鼠标悬停在该widget上时,就会显示出对应的形状。
setCursor(const QCursor& cursor) 设置该widget光标的形状,仅在鼠标停留在该widget上时生效
QGuiApplication::setOverrideCursor(const QCursor& cursor) 设置全局光标的形状,对整个程序中的所有widget都会生效。覆盖上面的setCursor设置的内容
  • cursor()、setCursor(const QCursor& cursor)是Widget级别的,同一个界面中,不同控件可以设置成不同的光标
  • QGuiApplication::setOverrideCursor(const QCursor& cursor):设置全局光标,程序内的全局,不是系统级别的全局
  1. 在Qt Designer中设置按钮的光标:
  • 创建一个按钮,在侧边栏的属性区域修改按钮光标(内置光标)
  • 通过代码来修改按钮光标

Qt内置光标

  1. 自定义鼠标光标
  • 准备一张图片(Qt.png),把图片导入到项目中(qrc),在代码访问到这张图片,基于图片构造出光标对象并设置
  • qrc和上面一样的操作,这里不再演示
  • 访问这个图片(使用QPixmap),图片是一个范围,不是一个点,当鼠标点击时,相当于图片的左上角进行点击。如果想要修改点击的位置,可以在QCursor cursor(pixmap)传入一个像素坐标:QCursor cursor(pixmap, 10, 10),(10, 10)即热点所在位置
cpp 复制代码
QPixmap pixmap(":/Qt.png");
QCursor cursor(pixmap);
cpp 复制代码
QPixmap pixmap(":/Qt.png");
QCursor cursor(pixmap, 10, 10);
this->setCursor(cursor);
  • 如果图片比较大,我们可以使用pixmap的scaled来进行缩放(注意:缩放不是修改图片本身,而是返回一个新的图片对象副本)
cpp 复制代码
pixmap = pixmap.scaled(100, 100); // 放大

font

API 说明
font() 获取当前widget的字体信息,返回QFont对象
setFont(const QFont& font) 设置当前widget的字体信息
  1. 设置字体属性(在右侧的属性编辑区,设置该label的font相关属性)
  2. 在代码中设置字体属性
  • 在界面中创建label,objectName 使用默认的label 即可
cpp 复制代码
    QLabel* label = new QLabel(this);
    label->setText("这是一个文本");

    //创造字体对象
    QFont font;
    font.setFamily("仿宋");
    font.setPixelSize(30);
    font.setBold(true);
    font.setItalic(true);
    font.setUnderline(true);
    font.setStrikeOut(true);

    label->setFont(font);

toolTip

  • GUI程序界面比较复杂,按钮较多,当你把鼠标悬停到这个控件上时就能弹出提示
API 说明
setToolTip 设置toolTip,鼠标悬停在该widget上时会有提示说明
setToolTipDuring 设置toolTip提示的时间,单位ms;时间到后toolTip自动消失
  1. 设置按钮的toolTip
  • 在界面上拖放两个按钮:objectName 设置为pushButton_yes 和pushButton_no
cpp 复制代码
    ui->pushButton_yes->setToolTip("这是yes按钮");
    ui->pushButton_yes->setToolTipDuration(3000);
    ui->pushButton_no->setToolTip("这是no按钮");
    ui->pushButton_no->setToolTipDuration(3000);

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. 理解不同的focusPolicy
  • 在界面上创建四个单行输入框(Line Edit)

  • 修改四个输入框的focusPolicy 属性为Qt::StrongFocus (默认取值,一般不用额外修改)

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

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

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

styleSheet

  • 通过CSS设置widget的样式
  • CSS (Cascading Style Sheets层叠样式表)本身属于网页前端技术。主要就是用来描述界面的样式。
  • 所谓"样式":包括不限于大小、位置、颜色、间距、字体、背景、边框等。我们平时看到的丰富多彩的网页就都会用到大量的CSS
  • CSS中可以设置的样式属性非常多。基于这些属性Qt只能支持其中一部分,称为QSS(Qt Style Sheet)。具体的支持情况可以参考Qt文档中"Qt Style Sheets Reference"章节
  1. 设置文本样式
  • 在界面上创建label
  • 右侧的styleSheet属性,设置样式
  • 此处的语法格式同CSS使用键值对的方式设置样式。其中键和值之间使用: 分割;键值对之间使用; 分割


  1. 通过代码来设置样式(实现一个"夜间模式"功能)
  • 日间模式:文字是黑色,背景是白色
  • 夜间模式:文字是白色,背景是黑色
  • 在界面上创建一个多行输入框(Text Edit或者plain Text Edit)和两个按钮:objectName分别为pushButton_light 和pushButton_dark
  • 编写按钮的槽函数
cpp 复制代码
void Widget::on_pushButton_light_clicked()
{
    //日间
    //设置窗口样式
    this->setStyleSheet("background-color:white;");
    //设置输入框样式
    ui->plainTextEdit->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->plainTextEdit->setStyleSheet("background-color:black; color: white;");
    //设置按钮样式
    ui->pushButton_light->setStyleSheet("color: white;");
    ui->pushButton_dark->setStyleSheet("color: white;");
}

关于计算机中的颜色表示:

  • 计算机中使用"像素"表示屏幕上的一个基本单位(也就是一个发亮的光点) 每个光点都使用三个字节表示颜色,分别是R(red),G(green),B(blue)一个字节表示(取值范围是0-255,或者0x00-0xFF)
  • 混合三种不同颜色的数值比例就能搭配出千千万万的颜色出来
  1. rgb(255, 0, 0) 或者#FF0000 或者#F00 表示纯红色
  2. rgb(0, 255, 0) 或者#00FF00 或者#0F0 表示纯绿色
  3. rgb(0, 0, 255) 或者#0000FF或者#00F 表示纯蓝色
  4. rgb(255, 255, 255) 或者#FFFFFF 或者#FFF 表示纯白色
  5. rgb(0, 0, 0) 或者#000000 或者#000 表示纯黑色
  • 当然,上述规则只是针对一般的程序而言是这么设定的。实际的显示器可能有8bit色深或者10bit色深等,实际情况会更加复杂
相关推荐
Coder_Boy_2 小时前
SpringAI与LangChain4j的智能应用-(实践篇4)
java·人工智能·spring boot·langchain
hqwest2 小时前
码上通QT实战02--登录设计
开发语言·qt·登录·ui设计·qt控件·qt布局·qt登录
忍冬行者2 小时前
kubeadm安装的k8s集群涉及etcd数据库的参数优化
数据库·kubernetes·etcd
资生算法程序员_畅想家_剑魔2 小时前
Java常见技术分享-13-多线程安全-锁机制-底层核心实现机制
java·开发语言
萤丰信息2 小时前
数智重构生态:智慧园区引领城市高质量发展新范式
java·大数据·人工智能·安全·智慧城市
大猫和小黄2 小时前
若依微服务Cloud中Quartz-Job模块适配OpenGauss数据库
数据库·微服务·opengauss·quartz·定时任务·若依·job
悟空码字2 小时前
MySQL分库分表,从“一室一厅”到“豪华别墅区”的数据库升级之旅
java·后端·mysql
Lisonseekpan2 小时前
RBAC 基于角色的访问控制模型详解与实践指南
java·服务器·网络·后端·spring·log4j