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

5.常用控件-QWidget|enabled|geometry|window frame(C++)

控件概述

实现图形化界面的程序.
Qt中已经给我们提供了很多的“控件"
![[Pasted image 20250418161607.png]]

就需要学习和了解这些控件,学会如何使用这些控件
编程讲究的是“站在巨人的肩膀上”,而不是“从头发明轮子"
一个图形化界面上的内容,不需要咱们全都从零去实现.Qt中已经提供了很多内置的控件了(按钮,文本框,单选按钮,复选按钮,下拉框.) 咱们拿过来就能直接使用.
![[Pasted image 20250418160915.png]]

QWidget核⼼属性

在Qt中,使⽤QWidget类表⽰"控件"。像按钮,视图,输⼊框,滚动条等具体的控件类,都是继承⾃QWidget.
可以说,QWidget中就包含了Qt整个控件体系中,通⽤的部分.
在QtDesigner中,随便拖⼀个控件过来,选中该控件,即可在右下⽅看到QWidget中的属性
![[Pasted image 20250418161043.png]]

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

核⼼属性概览
属性作⽤
enabled设置控件是否可使⽤. true 表⽰可⽤, false 表⽰禁⽤.
geometry位置和尺⼨.包含x,y,width,height四个部分.
其中坐标是以⽗元素为参考进⾏设置的.
windowTitle设置widget标题
windowIcon设置widget图标
windowOpacity设置widget透明度
cursor⿏标悬停时显⽰的图标形状.
是普通箭头,还是沙漏,还是⼗字等形状.
在Qt Designer界⾯中可以清楚看到可选项.
font字体相关属性.
涉及到字体家族,字体⼤⼩,粗体,斜体,下划线等等样式.
toolTip⿏标悬停在widget上会在状态栏中显⽰的提⽰信息.
toolTipDuringtoolTip显⽰的持续时间.
statusTipWidget状态发⽣改变时显⽰的提⽰信息(⽐如按钮被按下等).
whatsThis⿏标悬停并按下alt+F1时,显⽰的帮助信息(显⽰在⼀个弹出的窗⼝中).
styleSheet允许使⽤CSS来设置widget中的样式.
Qt中⽀持的样式⾮常丰富,对于前端开发⼈员上⼿是⾮常友好的.
focusPolicy该widget如何获取到焦点.
• Qt::NoFocus:控件不参与焦点管理,即⽆法通过键盘或⿏标获取焦点
• Qt::TabFocus:控件可以通过Tab键获得焦点
• Qt::ClickFocus:控件可以通过⿏标点击获得焦点
• Qt::StrongFocus:控件可以通过键盘和⿏标获得焦点
• Qt::WheelFocus:控件可以通过⿏标滚轮获得焦点(在某些平台或样式中可能不可⽤)
contextMenuPolicy上下⽂菜单的显⽰策略.
• Qt::DefaultContextMenu:默认的上下⽂菜单策略,⽤⼾可以通过⿏标右键或键盘快捷键触发上下⽂菜单
• Qt::NoContextMenu:禁⽤上下⽂菜单,即使⽤⼾点击⿏标右键也不会显⽰菜单
• Qt::PreventContextMenu:防⽌控件显⽰上下⽂菜单,即使⽤⼾点击⿏标右键也不会显⽰菜单
• Qt::ActionsContextMenu:将上下⽂菜单替换为控件的“动作”菜单,⽤⼾可以通过⿏标右键或键盘快捷键触发这个菜单
• Qt::CustomContextMenu:使⽤⾃定义的上下⽂菜单,⽤⼾可以通过⿏标右键或键盘快捷键触发这个菜单
locale设置语⾔和国家地区.
acceptDrops该部件是否接受拖放操作。
如果设置为true,那么该部件就可以接收来⾃其他部件的拖放操作。当⼀个部件被拖放到该部件上时,该部件会接收到相应的拖放事件(如dropEvent)。
如果设置为false,那么该部件将不会接收任何拖放操作。
minimumSize控件的最⼩尺⼨.包含最⼩宽度和最⼩⾼度.
maximumSize控件的最⼤尺⼨.包含最⼤宽度和最⼤⾼度.
sizePolicy尺⼨策略.设置控件在布局管理器中的缩放⽅式.
windowModality指定窗⼝是否具有"模态"⾏为.
sizeIncrement拖动窗⼝⼤⼩时的增量单位.
baseSize窗⼝的基础⼤⼩,⽤来搭配sizeIncrement调整组件尺⼨是计算组件应该调整到的合适的值.
palette调⾊板.可以设置widget的颜⾊⻛格.
mouseTracking是否要跟踪⿏标移动事件.
如果设为true,表⽰需要跟踪,则⿏标划过的时候该widget就能持续收到⿏标移动事件.
如果设为false,表⽰不需要跟踪,则⿏标划过的时候,widget不会收到⿏标移动事件,只能收到⿏标按下或者释放的事件.
tabletTracking是否跟踪触摸屏的移动事件.
类似于mouseTracking.Qt5.9中引⼊的新属性.
layoutDirection布局⽅向.
• Qt::LeftToRight:⽂本从左到右排列,也是默认值。
• Qt::RightToLeft:⽂本从右到左排列。
• Qt::GlobalAtomics:部件的布局⽅向由全局原⼦性决定(这个翻译其实有点尴尬.其实就是根据应⽤程序中的其他widget布局⽅向确的).
autoFillBackground是否⾃动填充背景颜⾊.
windowFilePath能够把widget和⼀个本地⽂件路径关联起来.
accessibleName设置widget的可访问名称.这个名称可以被辅助技术(像屏幕阅读器)获取到.这个属性⽤于实现⽆障碍程序的场景中(也就是给盲⼈写的程序).
accessibleDescription设置widget的详细描述.作⽤同accessibleName
inputMethodHints针对输⼊框有效,⽤来提⽰⽤⼾当前能输⼊的合法数据的格式.⽐如只能输⼊数字,只能输⼊⽇期等.

enabled

API说明
isEnabled()获取到控件的可⽤状态.
setEnabled设置控件是否可使⽤. true 表⽰可⽤, false 表⽰禁⽤.
  • 所谓"禁⽤"指的是该控件不能接收任何⽤⼾的输⼊事件,并且外观上往往是灰⾊的.
  • 如果⼀个widget被禁⽤,则该widget的⼦元素也被禁⽤
代码⽰例:使⽤代码创建⼀个禁⽤状态的按钮
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button = new QPushButton(this);button->setText("按钮");//按钮处于禁用状态button->setEnabled(false);
}Widget::~Widget()
{delete ui;
}

![[Pasted image 20250418165521.png]]

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button = new QPushButton(this);button->setText("按钮");//按钮处于禁用状态button->setEnabled(false);connect(button, &QPushButton::clicked, this, &Widget::handle);
}Widget::~Widget()
{delete ui;
}void Widget::handle()
{qDebug() << "handle";
}

加上槽函数,同样用不了

切换禁用状态
创建两个按钮
![[Pasted image 20250418170818.png]]

转到槽,分别给两个按钮插入clicked()

#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_clicked()
{qDebug() << "执行了槽函数";
}void Widget::on_pushButton_2_clicked()
{// 切换第一个按钮的禁用状态// 1.先获取到第一个按钮当前的状态bool enable = ui->pushButton->isEnabled();if (enable) {ui->pushButton->setEnabled(false);}else {ui->pushButton->setEnabled(true);}
}

运⾏程序,可以看到,初始情况下,上⾯的按钮是可⽤状态.
点击下⽅按钮,即可使上⽅按钮被禁⽤;再次点击下⽅按钮,上⽅按钮就会解除禁⽤.(禁⽤状态的按钮为灰⾊,且不可点击).
![[Pasted image 20250418172012.png]]

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对象了.

在Qt Designer中创建按钮的时候,可以设置按钮的初始状态是"可⽤"还是"禁⽤".
如果把enabled这⼀列的对钩去掉,则按钮的初始状态就是"禁⽤"状态.
![[Pasted image 20250418181800.png]]

geometry

位置和尺⼨.其实是四个属性的统称:

  • x 横坐标
  • y 纵坐标
  • width 宽度
  • height ⾼度
    ![[Pasted image 20250418183835.png]]

但是实际开发中,我们并不会直接使⽤这⼏个属性,⽽是通过⼀系列封装的⽅法来获取/修改.
对于Qt的坐标系,不要忘记是⼀个"左⼿坐标系".其中坐标系的原点是当前元素的⽗元素的左上⻆
![[Pasted image 20250418183901.png]]

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

Rect就是矩形
Qt中针对一些几何上的概念也进行了封装
QPoint表示一个点 QRect表示一个矩形
属于是小对象,里面的属性非常少,占用空间也小.
C++中使用上述对象,通常就会按照值的方式来传递参数了
move只是修改位置
setGeometry既可以修改位置,又可以修改尺寸~

代码⽰例:控制按钮的位置

![[Pasted image 20250418185512.png]]

创建一个按钮target
![[Pasted image 20250418185521.png]]

修改objectName为pushButton_target
修改这些属性的时候,一定要先确认好你当前选中的是哪个控件

![[Pasted image 20250418185722.png]]

1)在界⾯中拖五个按钮.
五个按钮的objectName分别为 pushButton_target , pushButton_up ,pushButton_down , pushButton_left , pushButton_right
五个按钮的初始位置和⼤⼩都随意
期望通过点击这几个按钮,就能够修改target按钮的geometry

#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_up_clicked()
{// 获取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;
}

![[Pasted image 20250418190311.png]]

单位都是像素

void Widget::on_pushButton_up_clicked()
{// 获取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setY(rect.y() - 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_down_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setY(rect.y() + 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_left_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setX(rect.x() - 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_right_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setX(rect.x() + 5);ui->pushButton_target->setGeometry(rect);
}

![[Pasted image 20250418191804.png]]

![[Pasted image 20250418191811.png]]

当前代码实际执行的效果,是在调整左上角位置.左上角位置改变的同时,高度和宽度也同时发生了改变
如果想要让这个按钮能够平移.(宽度高度不变,整个按钮的位置都发生改变)
刚才的代码,修改的是QRect对象的×和y.这样的修改就会使QRect宽度高度发生改变
如何才能实现“平移”的效果,保持尺寸不变,整个按钮位置变化?
不再修改QRect,而是通过QRect基于setGeometry第二个版本的函数重新设置位置即可.

void Widget::on_pushButton_up_clicked()
{// 获取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;
//    rect.setY(rect.y() - 5);
//    ui->pushButton_target->setGeometry(rect);ui->pushButton_target->setGeometry(rect.x(), rect.y() - 5, rect.width(), rect.height());
}void Widget::on_pushButton_down_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;
//    rect.setY(rect.y() + 5);
//    ui->pushButton_target->setGeometry(rect);ui->pushButton_target->setGeometry(rect.x(), rect.y() + 5, rect.width(), rect.height());
}void Widget::on_pushButton_left_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;
//    rect.setX(rect.x() - 5);
//    ui->pushButton_target->setGeometry(rect);ui->pushButton_target->setGeometry(rect.x() - 5, rect.y(), rect.width(), rect.height());
}void Widget::on_pushButton_right_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;
//    rect.setX(rect.x() + 5);
//    ui->pushButton_target->setGeometry(rect);ui->pushButton_target->setGeometry(rect.x() + 5, rect.y(), rect.width(), rect.height());
}

![[Pasted image 20250418193200.png]]

代码⽰例:⼀个表⽩程序

1)往界⾯上拖拽两个按钮和⼀个Label.
PushButton的objectName为 pushButton_accept 和 pushButton_reject ,label的objectName为 label
控件中⽂本如下图所⽰
![[Pasted image 20250418193844.png]]

void Widget::on_pushButton_accept_clicked()
{ui->label->setText("女神,嘴一个");
}

![[Pasted image 20250418194242.png]]

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 设置随机种子,使用时间戳作为随机种子srand(time(0));
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_accept_clicked()
{ui->label->setText("女神,嘴一个");
}void Widget::on_pushButton_reject_clicked()
{// 如果点击了这个按钮,就把这个按钮挪走// 通过生成随机数的方式来确定按钮新的位置// 获取到当前程序窗口的尺寸int width = this->geometry().width();int height = this->geometry().height();// 重新生成按钮的位置int x = rand() % width;int y = rand() % height;// 移动按钮的位置ui->pushButton_reject->move(x, y);
}

rand(是c标准库中的函数
能够生成一个随机的整数.这个数字范围很大~~
上述代码就类似于之前写猜数字,要生成一个1-100之间的整数

rand0 % 100 + 1
[0, 99] + 1 => [1, 100]

rand函数使用之前要设置随机种子~^
C语言中通过time可以获取到秒级时间戳~~
![[Pasted image 20250418195718.png]]

按钮提供的信号不止有点击
一下一上是点击,
不再使用clicked信号,换成pressed.鼠标按下的时候触发
![[Pasted image 20250418200054.png]]

void Widget::on_pushButton_reject_pressed()
{// 如果点击了这个按钮,就把这个按钮挪走// 通过生成随机数的方式来确定按钮新的位置// 获取到当前程序窗口的尺寸int width = this->geometry().width();int height = this->geometry().height();// 重新生成按钮的位置int x = rand() % width;int y = rand() % height;// 移动按钮的位置ui->pushButton_reject->move(x, y);
}

也可以做到,鼠标不点击,只要挪到按钮上,就会让按钮移动~~(需要使用到Qt中的事件机制)

window frame

如果widget作为⼀个窗⼝(带有标题栏,最⼩化,最⼤化,关闭按钮),那么在计算尺⼨和坐标的时候就有两种算法.包含window frame和不包含window frame.
其中x(),y(),frameGeometry(),pos(),move()都是按照包含window frame的⽅式来计算的.
其中geometry(),width(),height(),rect(),size()则是按照不包含window frame的⽅式来计算的.
当然,如果⼀个不是作为窗⼝的widget,上述两类⽅式得到的结果是⼀致的
![[Pasted image 20250418201635.png]]

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对象.
在Qt中,关于位置尺寸,提供了很多的API.
有的API的位置信息是以Widget本体左上角为原点的(不考虑Windowframe) 有的API的位置信息是以windowframe左上角为原点的.
geometry()
setGeometry()都是不考虑windowframe
frameGeometry()
setFrameGeometry()考虑windowframe
其实这⾥的API有frameGeometry和geometry两个就⾜够完成所有的需求了.
代码⽰例:感受geometry和frameGeometry的区别
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 直接针对Widget对象来使用geometry和frameGeometry。观察区别QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();qDebug() << rect1;qDebug() << rect2;
}Widget::~Widget()
{delete ui;
}

![[Pasted image 20250418205623.png]]

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

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 直接针对Widget对象来使用geometry和frameGeometry。观察区别
//    QRect rect1 = this->geometry();
//    QRect rect2 = this->frameGeometry();
//    qDebug() << rect1;
//    qDebug() << rect2;QPushButton* button = new QPushButton(this);button->setText("按钮");button->move(100, 100);connect(button, &QPushButton::clicked, this, &Widget::handle);
}Widget::~Widget()
{delete ui;
}void Widget::handle()
{QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();qDebug() << rect1;qDebug() << rect2;
}

![[Pasted image 20250418210248.png]]

相关文章:

  • nuxt3路由切换页面出不来,刷新可以
  • C++17 信号量模拟实现
  • Json 在线格式化 - 加菲工具
  • AUTOSAR图解==>AUTOSAR_SWS_E2ETransformer
  • Sigma-Delta ADC(ΣΔ-ADC)中的量化器简介
  • YOLOv11改进:基于小波卷积WTConv的大感受野目标检测网络-
  • 2048小游戏C++板来啦!
  • 3.Chromium指纹浏览器开发教程之chromium119版本源码拉取
  • Python实例题:Python批量获取王者荣耀皮肤
  • Leetcode刷题 由浅入深之哈希表——349. 两个数组的交集
  • 一级指针的介绍
  • 如何使用Labelimg查看已经标注好的YOLO数据集标注情况
  • webgl入门实例-12WebGL 投影矩阵 (Projection Matrix)基本概念
  • 电子级化学品除杂的必要性
  • java线程池原理及使用和处理流程
  • 【AI部署】腾讯云GPU-常见故障—SadTalker的AI数字人视频—未来之窗超算中心 tb-lightly
  • ESP8266简单介绍
  • cpolar 内网穿透 实现公网可以访问本机
  • 智能体时代的产业范式确立,中国企业以探索者姿态走出自己的路
  • 【卡洛诗】成为平价市场中的标杆西餐厅
  • 今年1-3月全国吸收外资2692.3亿元人民币
  • 2025年世界互联网大会亚太峰会数字金融论坛举行
  • 凭春晚分会场爆火的无锡,为何请来了上海主流媒体和网络大V
  • 跨境电商敦煌网在美下载量飙升,如何接住美国用户的“流量”?
  • 非盟特别会议聚焦美国关税政策,共商应对之法
  • 纯外卖店铺标榜“有堂食”并用虚假照片宣传,被罚1万元