当前位置: 首页 > 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.xdnf.cn/news/1290313.html

相关文章:

  • kernel pwn 入门(四) ret2dir详细
  • 大模型推理框架vLLM 中的Prompt缓存实现原理
  • GitHub分支保护介绍(Branch Protection)(git分支保护)(通过设置规则和权限来限制对特定分支的操作的功能)
  • 嵌入式系统学习Day17(文件编程-库函数调用)
  • AuthController类讲解
  • SQL 合并两个时间段的销售数据:FULL OUTER JOIN + COALESCE
  • 测试环境下因网络环境变化导致集群无法正常使用解决办法
  • SQL注入学习笔记
  • LeetCode Day5 -- 栈、队列、堆
  • 前后端分离项目中Spring MVC的请求执行流程
  • 肖臻《区块链技术与应用》第十讲:深入解析硬分叉与软分叉
  • 用 Spring 思维快速上手 DDD——以 Kratos 为例的分层解读
  • provide()函数和inject()函数
  • 数据结构:后缀表达式:结合性 (Associativity) 与一元运算符 (Unary Operators)
  • ZKmall开源商城的容灾之道:多地域部署与故障切换如何守护电商系统
  • 21.Linux HTTPS服务
  • 【GESP】C++一级知识点之【集成开发环境】
  • 备战国赛算法讲解——马尔科夫链,2025国赛数学建模B题详细思路模型更新
  • UE5.3 C++ 动态多播实战总结
  • SQL 生成日期与产品的所有组合:CROSS JOIN(笛卡尔积)
  • JVM宝典
  • 每日五个pyecharts可视化图表-line:从入门到精通 (4)
  • 什么时候用WS(WebSocket),什么使用用SSE(Server-Sent Events)?
  • Pytest项目_day13(usefixture方法、params、ids)
  • 机器学习处理文本数据
  • linux 开机进入initramfs无法开机
  • 串口通信学习
  • 数据分析专栏记录之 -基础数学与统计知识
  • Spring-Cache 缓存数据
  • windows git安装步骤