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

QT自适应布局中尺寸控制相关的resize、resizeEvent分析

最近开发qt项目,需要QPainter绘图和运行时widget的动态生成,考虑到项目的布局自适应,希望生成的widget控件和绘制的区域都能动态更改大小。因此对控件尺寸、布局管理一顿操作。由于一开始对resize和resizeEvent理解的不到位,走了很多弯路,比如信号与槽机制更新等,最后绕了一圈,还是回到resize和resizeEvent上。因此,在这里梳理一下,记录一下,分享一下。😊

两个关注点

  • 各个控件初始都有被设置成默认尺寸,经debugg测试发现,软件启动时,主窗体和子控件都会被触发一次resizeEvent事件。
  • 使用QPainter绘图,resizeEvent 事件中调用update()函数,会自动触发 paintEvent(QPaintEvent *event)方法。

resize函数

在Qt中,resize() 函数用于设置窗口或控件的大小。它是 QWidget 类的一个成员函数,用来动态地改变窗口或控件的大小。
调用该函数后,窗口或控件会立即更新其大小,会自动触发 resizeEvent 事件

resizeEvent 事件

resizeEvent 是一个虚拟函数,当窗口或控件的大小发生变化时被调用。在 Qt 的事件处理机制中,每当窗口大小发生变化时,都会生成一个 QResizeEvent 对象,并通过 resizeEvent 函数传递给相应的窗口或控件。

resizeEvent触发的场景

  1. 控件显示时的初始大小设置:
    当一个控件第一次显示时,其大小会被设置为初始值。这时会触发 resizeEvent。
  2. 控件的大小改变:
    如果控件的大小在运行时发生改变(例如调用了 resize() 函数),就会触发 resizeEvent。
  3. 窗口的大小改变:
    当窗口控件(如 QMainWindow、QDialog)的大小改变时,窗口中的所有子控件的 resizeEvent 会被触发。
  4. 布局管理器调整控件大小:
    如果控件使用了布局管理器(如 QVBoxLayout、QHBoxLayout 等),当父控件的大小改变时,布局管理器会自动调整其管理的子控件的大小,从而触发子控件的 resizeEvent。
  5. 窗口的最大化和最小化:
    当窗口被最大化或最小化时,窗口及其内部的所有控件的大小都会发生变化,从而触发 resizeEvent。
  6. 窗口内容的改变:
    如果控件内部的内容变化导致控件需要重新调整大小,也会触发 resizeEvent。例如,当控件内的文本内容增多导致控件需要扩展以显示全部内容时。
  7. 操作系统或窗口管理器的事件:
    某些情况下,操作系统或窗口管理器可能会发送窗口大小变化的事件,这也会导致 Qt 应用程序中的控件的 resizeEvent 被触发。

父子控件关系

子控件(子widget)的大小调整通常是由父控件(父widget)的 resize() 函数或其他导致父控件大小改变的操作来触发的。子控件的 resizeEvent 不需要直接由子控件自身的 resize() 函数来触发,而是依赖于父控件的大小变化,进而影响到子控件的布局和大小。

如何工作

  1. 父控件的 resize() 函数调用:
  • 当父控件的 resize() 函数被调用时,父控件的大小会立即改变。
  • Qt 的布局管理器(例如 QVBoxLayout、QHBoxLayout 等)通常会捕获父控件大小的变化,并据此调整其管理的子控件的大小和位置。
  1. 子控件的布局管理:
  • 如果子控件使用了布局管理器,布局管理器会响应父控件大小的变化,重新计算并调整子控件的大小和位置。
  • 如果子控件没有使用布局管理器,而是直接在 resizeEvent 中手动调整大小和位置,那么在父控件的 resizeEvent 中重新计算和调整子控件的大小通常是一个良好的做法。
  1. 子控件的 resizeEvent 事件:
  • 当父控件大小变化时,Qt 框架会自动管理子控件的 resizeEvent 事件的触发。
  • 子控件可以重写 resizeEvent 函数以响应其自身大小的变化,通常用于重新绘制内容或调整子控件内部布局。
#include <QtWidgets>class ChildWidget : public QWidget
{
public:ChildWidget(QWidget *parent = nullptr) : QWidget(parent) {}protected:void resizeEvent(QResizeEvent *event) override {qDebug() << "ChildWidget resized to:" << event->size();QWidget::resizeEvent(event); // 调用父类的resizeEvent处理}
};class ParentWidget : public QWidget
{
public:ParentWidget(QWidget *parent = nullptr) : QWidget(parent) {QVBoxLayout *layout = new QVBoxLayout(this);ChildWidget *childWidget = new ChildWidget(this);layout->addWidget(childWidget);}protected:void resizeEvent(QResizeEvent *event) override {qDebug() << "ParentWidget resized to:" << event->size();QWidget::resizeEvent(event); // 调用父类的resizeEvent处理}
};int main(int argc, char *argv[])
{QApplication app(argc, argv);ParentWidget parentWidget;parentWidget.resize(400, 300); // 设置初始大小parentWidget.setWindowTitle("Parent and Child Resize Example");parentWidget.show();return app.exec();
}

特殊情况

如果你的widget是运行时动态创建的,比如widgetA类和widgetB类都继承QWidget类,都设定了布局管理,都是new出来的,A当作B的对象,当给A进行resize的时候,并没有自动触发B中的resizeEvent事件,而是要对B类对象进行resize才能触发相关事件
项目比较复杂,debugg过程确实进入不到相应断点,没有单独测试,感兴趣的小伙伴自行测试一下。

动态创建widget事件绑定

在Qt中,installEventFilter是一个用于将事件过滤器安装到另一个对象的方法。当一个对象安装了事件过滤器后,它会接收到其过滤目标对象的所有事件,并且可以决定是否允许或拒绝这些事件。事件过滤器是Qt事件系统的一部分,用于在事件传播到目标对象之前对其进行拦截和修改。

#include <QApplication>
#include <QWidget>
#include <QMouseEvent>
#include <QEvent>class EventFilter : public QObject {Q_OBJECT
public:EventFilter(QObject *parent = nullptr) : QObject(parent) {// 创建事件过滤器}protected:bool eventFilter(QObject *watched, QEvent *event) override {// 过滤目标对象为QWidgetif (watched == widget) {// 过滤事件为鼠标按下事件if (event->type() == QEvent::MouseButtonPress) {// 处理鼠标按下事件QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);qDebug() << "Mouse button pressed at:" << mouseEvent->pos();return true; // 阻止事件传递给目标对象}}return false; // 允许事件传递给目标对象}private:QWidget *widget; // 需要安装事件过滤器的QWidget
};int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建一个QWidgetQWidget *myWidget = new QWidget();myWidget->resize(200, 200);// 创建事件过滤器EventFilter *eventFilter = new EventFilter();// 将事件过滤器安装到QWidgetmyWidget->installEventFilter(eventFilter);// 显示QWidgetmyWidget->show();return app.exec();
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【前端手写代码】手写instanceof方法
  • Python 中的 NotImplemented 和 NotImplementedError
  • HTTP协议详解(一)
  • 并发编程工具集——Future(二十七)
  • 【CPS出版】2024年智能计算与数据分析国际学术会议(ICDA 2024,9月6日-8)
  • 压缩技巧:word怎么压缩到10m以下?word压缩,快速学会的5个高效方法!
  • vue el-input 输入框下拉显示匹配数据
  • 一文带你掌握C++异常处理
  • FPGA开发——数码管的使用(二)
  • 敏捷开发笔记(第14章节)--TEMPLATE METHOD模式和STRATEGY模式:继承与委托
  • 【第四节】python面向对象
  • 基于 LangChain 开发应用程序第七章-代理
  • 781页 | 2024全国数据资产政策法规汇编(可下载)
  • 富唯智能转运机器人:高效、智能、未来的选择
  • 代码随想录算法训练营第二十六天|452. 用最少数量的箭引爆气球、435. 无重叠区间、763.划分字母区间
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • ES学习笔记(12)--Symbol
  • HTTP请求重发
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Java比较器对数组,集合排序
  • Java到底能干嘛?
  • k8s如何管理Pod
  • PHP CLI应用的调试原理
  • PV统计优化设计
  • SQL 难点解决:记录的引用
  • 从伪并行的 Python 多线程说起
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 基于HAProxy的高性能缓存服务器nuster
  • 将回调地狱按在地上摩擦的Promise
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 力扣(LeetCode)56
  • 入口文件开始,分析Vue源码实现
  • 我是如何设计 Upload 上传组件的
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • 湖北分布式智能数据采集方法有哪些?
  • 选择阿里云数据库HBase版十大理由
  • 昨天1024程序员节,我故意写了个死循环~
  • # windows 运行框输入mrt提示错误:Windows 找不到文件‘mrt‘。请确定文件名是否正确后,再试一次
  • # 飞书APP集成平台-数字化落地
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #QT(串口助手-界面)
  • (1)(1.11) SiK Radio v2(一)
  • (C)一些题4
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (二十六)Java 数据结构
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (力扣题库)跳跃游戏II(c++)
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案