Qt实现手动切换多种布局

引言

之前写了一个手动切换多个布局的程序,下面来记录一下。
程序运行效果如下:
在这里插入图片描述

示例

需求

通过点击程序界面上不同的布局按钮,使主工作区呈现出不同的页面布局,多个布局之间可以通过点击不同布局按钮切换。支持的最多的窗口为9个。不同布局下窗口数随之变化。

开发环境

使用的QtCreator12.0.2,基于Qt5.15.2库开发。

代码实现

创建基于QApplication的应用程序。
下面是实现代码:
main.cpp

#include "manullayoutdialog.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);ManulLayoutDialog w;w.show();ObjectPooling*m_pool = ObjectPooling::getInstance(9);return a.exec();
}

ObjectPooling.h

#ifndef OBJECTPOOLING_H
#define OBJECTPOOLING_H#include <QObject>
#include <QWidget>
#include <QVector>class ObjectPooling:public QObject
{Q_OBJECT
private:ObjectPooling(qint32 num);ObjectPooling(const ObjectPooling &) = delete;ObjectPooling& operator=(const ObjectPooling&)=delete;
public:static ObjectPooling *getInstance(qint32 num);~ObjectPooling();QWidget* takeOut();void putIn(QWidget *pWidget);int getSize()const;
private:QVector<QWidget*> m_vecWidget;
};#endif // OBJECTPOOLING_H

ObjectPooling.cpp

#include "objectpooling.h"
#include <qDebug>ObjectPooling::ObjectPooling(qint32 num):QObject() {for(int i = 0; i < num;++i){QWidget *pWidget = new QWidget;if(pWidget){pWidget->setStyleSheet("background-color:back;");m_vecWidget.push_back(pWidget);}}
}ObjectPooling *ObjectPooling::getInstance(qint32 num)
{static ObjectPooling instance(num);return &instance;
}ObjectPooling::~ObjectPooling()
{if(m_vecWidget.size()<1)return;for(auto it = m_vecWidget.begin();it != m_vecWidget.end();++it){if(*it){delete *it;(*it) = nullptr;}}m_vecWidget.clear();
}QWidget *ObjectPooling::takeOut()
{if(m_vecWidget.size()){QWidget*pWidget = m_vecWidget.back();
//        qDebug()<<"takeOut-befor : "<<m_vecWidget.size();m_vecWidget.pop_back();
//       qDebug()<<"takeOut-back : "<<m_vecWidget.size();return pWidget;}qDebug()<<"对象池没有对象了!!";return nullptr;
}void ObjectPooling::putIn(QWidget *pWidget)
{m_vecWidget.push_back(pWidget);
}int ObjectPooling::getSize() const
{return m_vecWidget.size();
}

ManulLayoutDialog.h

#ifndef MANULLAYOUTDIALOG_H
#define MANULLAYOUTDIALOG_H#include <QDialog>
#include "objectpooling.h"QT_BEGIN_NAMESPACE
namespace Ui {
class ManulLayoutDialog;
}
QT_END_NAMESPACEclass ManulLayoutDialog : public QDialog
{Q_OBJECTpublic:ManulLayoutDialog(QWidget *parent = nullptr);~ManulLayoutDialog();
private:void initLayout();void clearLastLayout(int n);//n——新的布局中窗口的总数void threeColumnLayout(int r,int c);//r——行数,c——列数
private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_pushButton_3_clicked();void on_pushButton_4_clicked();void on_pushButton_5_clicked();private:Ui::ManulLayoutDialog *ui;qint32 m_n;//布局中窗口的总个数QVector<QWidget*> m_vecWidget;//保存布局中的窗口ObjectPooling* m_pool;
};
#endif // MANULLAYOUTDIALOG_H

ManulLayoutDialog.cpp

#include "manullayoutdialog.h"
#include "ui_manullayoutdialog.h"
#include <QDebug>ManulLayoutDialog::ManulLayoutDialog(QWidget *parent): QDialog(parent), ui(new Ui::ManulLayoutDialog)
{ui->setupUi(this);initLayout();
}ManulLayoutDialog::~ManulLayoutDialog()
{for(QWidget *pWidget:m_vecWidget){pWidget->setParent(nullptr);//不设置被回收的窗口父对象为空,会被再次释放ObjectPooling::getInstance(9)->putIn(pWidget);}m_vecWidget.clear();delete ui;//若被回收的窗口没有设置父对象为空,这里会析构该窗口,回收到对象池后会再次析构
}void ManulLayoutDialog::initLayout()
{QHBoxLayout *pHLayout = new QHBoxLayout(ui->widget);pHLayout->setContentsMargins(0,0,0,0);QWidget *pWidget = ObjectPooling::getInstance(9)->takeOut();pHLayout->addWidget(pWidget);m_n = 1;m_vecWidget.push_back(pWidget);m_pool = ObjectPooling::getInstance(9);
}void ManulLayoutDialog::clearLastLayout(int n)
{QLayout *pLayout = ui->widget->layout();
//    qDebug()<<"移除前的窗口数m_vecWidget: "<<m_vecWidget.size();if(m_n>n){for(int i =0; i <m_n -n;++i){//趟数//移除窗口中的控件,回收到对象池QWidget *pWidget = m_vecWidget.back();if(pLayout && pWidget){qDebug()<<"准备移除窗口===";pLayout->removeWidget(pWidget);pWidget->setParent(nullptr);m_vecWidget.pop_back();}// if(pLayout){qDebug()<<"布局不为空 ";}// if(pWidget){qDebug()<<"窗口不为空 ";}// QWidget *fWidget = pWidget->parentWidget();ObjectPooling::getInstance(9)->putIn(pWidget);// qDebug()<<"对象池窗口数m_vecWidget: "<<ObjectPooling::getInstance(9)->getSize();// qDebug()<<"移除后的窗口数m_vecWidget: "<<m_vecWidget.size();}}else if(m_n <n){//为了防止二次重设父对象,先将上一次的父对象清空for(auto it = m_vecWidget.begin();it != m_vecWidget.end();++it){if(*it){(*it)->setParent(nullptr);}}for(int i = 0; i < n-m_n;++i){m_vecWidget.push_back(ObjectPooling::getInstance(9)->takeOut());}}//删除窗口原本的布局delete pLayout;//    ui->widget->setLayout(nullptr);
}void ManulLayoutDialog::threeColumnLayout(int r, int c)
{int total = r*c;if(m_n == total){return ;}clearLastLayout(total);QGridLayout *pGridLayout = new QGridLayout(ui->widget);pGridLayout->setContentsMargins(0,0,0,0);for(int i = 0; i < r;++i){for(int j = 0; j < c; ++j){pGridLayout->addWidget(m_vecWidget[i+j+2*i],i,j);//找下标对应的位置与元素之间的关系}}m_n = total;
}void ManulLayoutDialog::on_pushButton_clicked()
{if(m_n == 1){return ;}else{clearLastLayout(1);}QHBoxLayout *pHLayout = new QHBoxLayout(ui->widget);pHLayout->setContentsMargins(0,0,0,0);// qDebug()<<"布局1中的窗口数m_vecWidget: "<<m_vecWidget.size();pHLayout->addWidget(m_vecWidget.back());m_n = 1;
}void ManulLayoutDialog::on_pushButton_2_clicked()
{if(m_n == 2){return ;}else if(m_n > 2){clearLastLayout(2);QHBoxLayout *pLayout = new QHBoxLayout(ui->widget);pLayout->setContentsMargins(0,0,0,0);for(auto it = m_vecWidget.begin();it != m_vecWidget.end();++it){pLayout->addWidget(*it);}}else{QLayout *pLayout = ui->widget->layout();QWidget *pWidget = ObjectPooling::getInstance(9)->takeOut();pLayout->addWidget(pWidget);m_vecWidget.push_back(pWidget);}m_n = 2;// qDebug()<<"布局2中的窗口数m_vecWidget: "<<m_vecWidget.size();
}void ManulLayoutDialog::on_pushButton_3_clicked()
{if(m_n == 4){return ;}clearLastLayout(4);//只能先清理之前的布局,不能与下面的新布局互换位置QGridLayout *pGridLayout = new QGridLayout(ui->widget);pGridLayout->setContentsMargins(0,0,0,0);for(int i = 0; i < 2;++i){for(int j = 0; j < 2; ++j){pGridLayout->addWidget(m_vecWidget[i+j+i],i,j);//找下标对应的位置与元素之间的关系}}m_n = 4;
}void ManulLayoutDialog::on_pushButton_4_clicked()
{threeColumnLayout(2,3);
}void ManulLayoutDialog::on_pushButton_5_clicked()
{threeColumnLayout(3,3);
}

运行结果

选一种的2行6列布局下的效果的截图。具体的运行效果和文章开始的效果一样。
在这里插入图片描述

程序分析

项目中先创建了一个单例模式下的对象池,负责布局中总窗口的创建、回收,取出、以及存入。同时创建了一个手动布局类ManulLayoutDialog,在该类中实现了在界面上点击不同布局按钮的响应,ObjectPooling类作为手动布局类ManulLayoutDialog的成员函数,两个类之间是一种关联的关系。采用队列存放布局中的窗口,当要切换的布局中的窗口数大于当前的窗口布局中的窗口数,则先清除之前的窗口布局,将布局中的窗口回收到窗口数组中,同时向对象池中取出相差数量的窗口,放入窗口数组,创建新的布局,将窗口数组中的窗口加入新布局;当要切换的布局中的窗口数小于当前的窗口布局中的窗口数,则先从布局中移除相差数量的窗口,将移除的窗口从窗口数组中去除,删除窗口原来的布局,同时将移除的窗口存入对象池中,创建新的布局,将窗口数组中的窗口加入到新的布局。

注意

示例中有两个需要注意的点:
1.对象池中窗口的释放。 可看ManulLayoutDialog的析构函数。
2.原本布局中窗口的回收。 可看clearLastLayout函数。
上面的两点在代码的注释中有写,是为重点注意项。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39046.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

burpsuite 设置监听窗口 火狐利用插件快速切换代理状态

一、修改burpsuite监听端口 1、首先打开burpsuite&#xff0c;点击Proxy下的Options选项&#xff1a; 2、可以看到默认的监听端口为8080&#xff0c;首先选中我们想要修改的监听&#xff0c;点击Edit进行编辑 3、将端口改为9876&#xff0c;并保存 4、可以看到监听端口修改成功…

typescript学习回顾(五)

今天来分享一下ts的泛型&#xff0c;最后来做一个练习 泛型 有时候&#xff0c;我们在书写某些函数的时候&#xff0c;会丢失一些类型信息&#xff0c;比如我下面有一个例子&#xff0c;我想提取一个数组的某个索引之前的所有数据 function getArraySomeData(newArr, n:numb…

JVM原理(十):JVM虚拟机调优分析与实战

1. 大内存硬件上的程序部署策略 这是笔者很久之前处理过的一个案例&#xff0c;但今天仍然具有代表性。一个15万PV/日左右的在线文档类型网站最近更换了硬件系统&#xff0c;服务器的硬件为四路志强处理器、16GB物理内存&#xff0c;操作系统为64位CentOS5.4&#xff0c;Resin…

阿里云centos 取消硬盘挂载并重建数据盘信息再次挂载

一、取消挂载 umount [挂载点或设备] 如果要取消挂载/dev/sdb1分区&#xff0c;可以使用以下命令&#xff1a; umount /dev/sdb1 如果要取消挂载在/mnt/mydisk的挂载点&#xff0c;可以使用以下命令&#xff1a; umount /mnt/mydisk 如果设备正忙&#xff0c;无法立即取消…

系统安全及应用(命令)

目录 一、账号安全控制 1.1 系统账号清理 1.2 密码安全控制 1.3 历史记录控制 1.4 终端自动注销 二、系统引导和登陆控制 2.1 限制su命令用户 2.2 PAM安全认证 示例一&#xff1a;通过pam 模块来防止暴力破解ssh 2.3 sudo机制提升权限 2.3.1 sudo命令&#xff08;ro…

Java的日期类常用方法

Java_Date 第一代日期类 获取当前时间 Date date new Date(); System.out.printf("当前时间" date); 格式化时间信息 SimpleDateFormat simpleDateFormat new SimpleDateFormat("yyyy-mm-dd hh:mm:ss E); System.out.printf("格式化后时间" si…

【windows|012】光猫、路由器、交换机详解

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

windows USB 驱动开发-URB结构

通用串行总线 (USB) 客户端驱动程序无法直接与其设备通信。 相反&#xff0c;客户端驱动程序会创建请求并将其提交到 USB 驱动程序堆栈进行处理。 在每个请求中&#xff0c;客户端驱动程序提供一个可变长度的数据结构&#xff0c;称为 USB 请求块 (URB) &#xff0c;URB 结构描…

ctfshow-web入门-命令执行(web75-web77)

目录 1、web75 2、web76 3、web77 1、web75 使用 glob 协议绕过 open_basedir&#xff0c;读取根目录下的文件&#xff0c;payload&#xff1a; c?><?php $anew DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString(). ); } ex…

读书笔记-Java并发编程的艺术-第3章(Java内存模型)-第9节(Java内存模型综述)

3.9 Java内存模型综述 前面对Java内存模型的基础知识和内存模型的具体实现进行了说明。下面对Java内存模型的相关知识做一个总结。 3.9.1 处理器的内存模型 顺序一致性内存模型是一个理论参考模型&#xff0c;JMM和处理器内存模型在设计时通常会以顺序一致性内存模型为参照。…

C#/WPF 自制白板工具

随着电子屏幕技术的发展&#xff0c;普通的黑板已不再适用现在的教学和演示环境&#xff0c;电子白板应运而生。本篇使用WPF开发了一个电子白板工具&#xff0c;功能丰富&#xff0c;非常使用日常免费使用&#xff0c;或者进行再次开发。 示例代码如下&#xff1a; Stack<St…

拓扑排序[讲课留档]

拓扑排序 拓扑排序要解决的问题是给一个有向无环图的所有节点排序。 即在 A O E AOE AOE网中找关键路径。 前置芝士&#xff01; 有向图&#xff1a;有向图中的每一个边都是有向边&#xff0c;即其中的每一个元素都是有序二元组。在一条有向边 ( u , v ) (u,v) (u,v)中&…

ChatGPT 官方发布桌面端,向所有用户免费开放

Open AI 官方已经发布了适用于 macOS 的 ChatGPT 桌面端应用。 此前&#xff0c;该应用一直处于测试阶段&#xff0c;仅 Plus 付费订阅用户可以使用。 目前已面向所有用户开放&#xff0c;所有 Mac 用户均可免费下载使用。 我们可以访问官网下载安装包&#xff1a;https://op…

2024 年江西省研究生数学建模竞赛题目 B题投标中的竞争策略问题--完整思路、代码结果分享(仅供学习)

招投标问题是企业运营过程中必须面对的基本问题之一。现有的招投标平台有国家级的&#xff0c;也有地方性的。在招投标过程中&#xff0c;企业需要全面了解招标公告中的相关信息&#xff0c;在遵守招投标各种规范和制度的基础上&#xff0c;选择有效的竞争策略和技巧&#xff0…

基于JSP技术的校园餐厅管理系统

开头语&#xff1a; 你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果您对校园餐厅管理系统感兴趣或有相关需求&#xff0c;欢迎随时联系我。我的联系方式在文末&#xff0c;期待与您交流&#xff01; 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#x…

QT的编译过程

qmake -project 用于从源代码生成项目文件&#xff0c;qmake 用于从项目文件生成 Makefile&#xff0c;而 make 用于根据 Makefile 构建项目。 详细解释&#xff1a; qmake -project 这个命令用于从源代码目录生成一个初始的 Qt 项目文件&#xff08;.pro 文件&#xff09;。它…

Keil5中:出现:failed to execute ‘...\ARMCC\bin\ArmCC‘

点三个点&#xff0c;去自己的磁盘找自己的ARM\ARMCC\bin

深入解析:计算机系统总线全方位解读

在计算机组成原理中&#xff0c;总线系统是连接计算机各个部件的重要通道。本文将详细介绍系统总线的基本概念、分类、特性及性能指标、结构和控制方式。希望通过本文的讲解&#xff0c;能够帮助基础小白更好地理解计算机系统总线的工作原理。 系统总线 (System Bus) 系统总线…

selenium 简介以及 selenium 环境配置

文章目录 一、初识 selenium1.selenium 简介2.selenium 三大组件3.selenium工作过程和原理4.selenium自动化测试流程5.selenium优点 二、自动化测试1.UI自动化本质2.UI自动化的前提3.适用场景4.UI自动化的原则5.UI自动化的覆盖率 三、selenium 环境配置 一、初识 selenium 1.s…

单点登录demo

gitee.com 搜索xxl(许雪里) 的sso 操作demo 完整流程图