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

【Qt开发】常用控件(三) -> geometry

目录

1 -> 控件的位置和尺寸

2 -> 相关 API

3 -> 代码示例

3.1 -> 控制按钮的位置

3.2 -> 表白程序


1 -> 控件的位置和尺寸

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

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

但是在实际开发中,并不会直接使用这几个属性,而是通过一系列封装的方法来获取/修改。

对于 Qt 的坐标系,使用的是 “左手坐标系”,其中坐标系的原点是当前元素的父元素的左上角。

API说明
geometry()获取到控件的位置和尺寸,返回结果是一个 QRect,包含了x,y,width,height。其中x,y 是左上角的坐标

setGeometry(QRect)

setGeometry(int x, int y, int widrh, int height)

设置控件的位置和尺寸,可以直接设置一个 QRect,也可以分四个属性单独设置

2 -> 相关 API

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

通过观察可以发现,其实这里的 API 有 frameGeometry 和 geometry 两个就足够完成所有需求了。为什么还要提供那么多功能重复的 API 呢?

这就涉及到 Qt API 的设计理念了:尽量符合人的直觉。

举个例子感受 geometry 和 frameGeometry 的区别

1. 在界面上放置一个按钮

2. 在按钮的 slot 函数中,编写代码

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

3. 在构造函数中,也添加同样的代码

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();qDebug() << rect1;qDebug() << rect2;
}

执行程序,可以看到,在构造函数中,打印出的 geometry 和 frameGeometry 是相同的。

但是在点击按钮时,打印的 geometry 和 frameGeometry 则存在差异。

注意:

在构造方法中,Widget 刚刚创建出来,还没有加入到对象树中,此时也就不具备 Window frame。

在按钮的 slot 函数中,由于用户点击的时候,对象树已经构造好了,此时 Widget 已经具备了 Window frame,因此在位置和尺寸上均出现了差异。

如果把上述代码修改成打印 pushButton 的 geometry 和 frameGeometry,结果就是完全相同的。因为 pushButton 并非是一个窗口。

3 -> 代码示例

3.1 -> 控制按钮的位置

1. 在界面上拖动五个按钮

五个按钮的 objectName 分别是 pushButton_target,pushButton_up,pushButton_down,pushButton_left,pushButton_right。

五个按钮的初始位置和大小自行设计。

2. 在 widget.cpp 中编写四个按钮的 slot 函数

 修改QRect对象的x和y,使QRect的高度宽度发生变化
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()
{// 获取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setY(rect.y() + 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_left_clicked()
{// 获取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setX(rect.x() - 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_right_clicked()
{// 获取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setX(rect.x() + 5);ui->pushButton_target->setGeometry(rect);
}

运行程序可以看到,按下下方的按钮,就会控制 target 的左上角的位置。对应的按钮整个尺寸也会发生改变。

上述代码中是直接设置的 QRect 中的 x,y。实际上 QRect 内部是存储了左上和右下两个点的坐标,再通过这两个点的坐标差值计算长宽。

单纯修改左上坐标就会引起整个矩形的长宽发生改变。

如果想让整个按钮都移动,可以改成下列代码

// 平移target
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()
{// 获取到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_left_clicked()
{// 获取到target本身的geometryQRect 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()
{// 获取到target本身的geometryQRect 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());}

3.2 -> 表白程序

1. 往界面上拖拽两个按钮和一个 Label。

Label 的 objectName 为 pushButton_true 和 pushButton_false,label 的 objectName 为 label

2. 在 widget.cpp 中添加 slot 函数

void Widget::on_pushButton_true_clicked()
{ui->label->setText("好耶么么(*  ̄3)(ε ̄ *)");
}void Widget::on_pushButton_false_clicked()
{// 如果点击,就把按钮挪走// 可以通过随机数,来确定按钮新的位置int width = this->geometry().width();int height = this->geometry().height();// 重新生成按钮位置// 使用rand函数之前要设置随机种子int x = rand() % width;int y = rand() % height;// 移动按钮位置ui->pushButton_false->move(x, y);
}

运行程序可以看到,当点击 “否” 时,按钮就跑了。

上述代码使用的是 pressed,鼠标按下事件。如果使用 mouseMoveEvent,只要鼠标移动过来,按钮就跑了。

window frame 的影响

如果 widget 作为一个窗口(带有标题栏、最小化、最大化、关闭按钮),那么在计算尺寸和坐标的时候就有两种算法,包含 window frame 和不包含 window frame。

其中 x(),y(),frameGeometry(),pos(),move() 都是按照包含 window frame 的方式来计算的。

其中 geometry(),width(),height(),rect(),size() 则是按照不包含 window frame 的方式来计算的。

如果一个不是作为窗口的 widget,上述两类方式得到的结果是一致的。


感谢各位大佬支持!!!

互三啦!!!

http://www.lryc.cn/news/619266.html

相关文章:

  • 疏老师-python训练营-Day44预训练模型
  • php7 太空船运算符
  • Linux 软件编程:文件IO、目录IO、时间函数
  • 适配安卓15(对应的sdk是35)
  • RxJava 在 Android 中的深入解析:使用、原理与最佳实践
  • 大牌点餐接口api对接全流程
  • 《吃透 C++ 类和对象(中):构造函数与析构函数的核心逻辑》
  • Ubuntu22.04轻松安装Qt与OpenCV库
  • 药房智能盘库系统的Python编程分析与实现—基于计算机视觉与时间序列预测的智能库存管理方案
  • 基于大数据spark的医用消耗选品采集数据可视化分析系统【Hadoop、spark、python】
  • 分段锁和限流的间接实现
  • 通信中间件 Fast DDS(一) :编译、安装和测试
  • 机器学习—— TF-IDF文本特征提取评估权重 + Jieba 库进行分词(以《红楼梦》为例)
  • CMake进阶: 使用FetchContent方法基于gTest的C++单元测试
  • LINUX812 shell脚本:if else,for 判断素数,创建用户
  • 【GESP】C++一级知识点之【集成开发环境】
  • TF-IDF:信息检索与文本挖掘的统计权重基石
  • [SC]如何使用sc_semaphore实现对共享资源的访问控制
  • 初识神经网络04——构建神经网络2
  • 【从零开始java学习|第四篇】IntelliJ IDEA 入门指南
  • Redis序列化配置类
  • uni-app实战教程 从0到1开发 画图软件 (学会画图)
  • 基于STC8单片机的RTC时钟实现:从原理到实践
  • 聚合搜索中的设计模式
  • 数据结构:中缀到后缀的转换(Infix to Postfix Conversion)
  • 开发避坑指南(23):Tomcat高版本URL特殊字符限制问题解决方案(RFC 7230 RFC 3986)
  • 一键设置 NTP 时区的脚本(亲测,适用于部署 K8S 的前置环境)
  • 数据结构:图
  • 终端安全与网络威胁防护笔记
  • Web 服务详解:HTTP 与 HTTPS 配置