效果

Demo工程源码
https://download.csdn.net/download/qq_41673920/20217378

https://gitee.com/TANG_N/QSplitterDemo

实现思路

我们需要两个接口
分割控件的接口,选中一个控件,在这个控件上一分为二
删除控件接口,选中一个控件,删除掉
QSplitter功能比较基础,利用QSplitter我们可以实现像QtCreator编辑器随意拆分的效果

先看窗口结构,总共有三种实现方式。绿色方框的是添加的控件QWidget,黑色的是拆分器QSplitter只有模型一的默认分割出来才是1:1。逐个解释一下

模型一
每个Widget都被单独的一个QSplitter装载,一个QSplitter最多装载两个QSplitter,这么做浪费了很多QSplitter,比如3号那个,其实一个QSplitter就能搞定了。但是这样的好处是每次新建都会1:1的拆分,后面两种模型都不能1:1拆分,不知道什么原因,有搞定的欢迎回复

模型二
相比模型一,已经节约了不少QSplitter,但是拆分的widget不是默认1:1的,思考这个模型,QSplitter还可以精简,每个QSplitter还是只能装两个

模型三
这个是一个Splitter可以装任意多个Widget,最节约内存,但是和模型二一样拆分后不是1:1的

模型一实现添加

如上图,我们水平拆分绿色控件1,每一个控件需被一个Splitter装载(因为这样很方便,暂且这么实现),直接把2设置成水平拆分器,然后新建两个Splitter,分别装载选中的控件1,和新加的控件src,最后把新建的两个QSplitter装入2就完成了,如下图,是不是很简单

模型一实现删除

删除就比较简单了,以上图为例,想删掉箭头所指绿色控件1,把1,2,3删除,然后把上边那么那个QSplitter填入3所占的空就ok了


其他两种实现看代码吧

代码

CSplitter.cpp

#include "CSplitter.h"
#include <QHBoxLayout>
#include <QDebug>CSplitter::CSplitter(QWidget *parent) : QWidget(parent)
{QHBoxLayout *pLayout = new QHBoxLayout(this);pLayout->setContentsMargins(0,0,0,0);
}/* @dst:将要分割的已存在的控件* @src:新加的控件* @orientation:分割方向
*/
void CSplitter::addWidget(QWidget *dst, QWidget *src, Qt::Orientation orientation)
{if(!src)return ;if ((nullptr == dst) || (0 == this->layout()->count())){QSplitter *pSplitter = new QSplitter(this);pSplitter->addWidget(src);this->layout()->addWidget(pSplitter);}else{QSplitter *pPSplitter = qobject_cast<QSplitter *>(dst->parentWidget());if (!pPSplitter)return ;pPSplitter->setOrientation(orientation);QSplitter *pSplitterDst = new QSplitter(this);pSplitterDst->addWidget(dst);QSplitter *pSplitterSrc = new QSplitter(this);pSplitterSrc->addWidget(src);pPSplitter->addWidget(pSplitterDst);pPSplitter->addWidget(pSplitterSrc);}
}void CSplitter::removeWidget(QWidget *src)
{if(!src || !src->parentWidget())return ;QSplitter *pPPSplitter = qobject_cast<QSplitter *>(src->parentWidget()->parentWidget());if (nullptr == pPPSplitter){if(qobject_cast<QSplitter *>(src->parentWidget()))delete src->parentWidget(); //src & splitter}else{QSplitter *pUSplitter = (QSplitter *)pPPSplitter->widget(!pPPSplitter->indexOf(src->parentWidget())); //QSplitter只会装两个 index非0即1QSplitter *pPPPSplitter = qobject_cast<QSplitter *>(pPPSplitter->parentWidget());if (nullptr == pPPPSplitter) {this->layout()->addWidget(pUSplitter);} else {pPPPSplitter->insertWidget(pPPPSplitter->indexOf(pPPSplitter),pUSplitter);}delete pPPSplitter; //删除src 删除pSplitter}qDebug()<<"开始打印剩余控件------------";recursiveInstallEventFilter(this);qDebug()<<"打印完成------------";
}void CSplitter::addWidget2(QWidget *dst, QWidget *src, Qt::Orientation orientation)
{if(!src)return ;if ((nullptr == dst) || (0 == this->layout()->count())){QSplitter *pSplitter = new QSplitter(orientation,this);pSplitter->addWidget(src);this->layout()->addWidget(pSplitter);}else{QSplitter *pPSplitter = qobject_cast<QSplitter *>(dst->parentWidget());if(pPSplitter->count() > 1){QSplitter *pSplitter = new QSplitter(orientation,this);pPSplitter->insertWidget(pPSplitter->indexOf(dst),pSplitter);pSplitter->addWidget(dst);pSplitter->addWidget(src);}else{pPSplitter->setOrientation(orientation);pPSplitter->addWidget(src);}}
}void CSplitter::removeWidget2(QWidget *src)
{if(!src || !src->parentWidget())return ;QSplitter *pPSplitter = qobject_cast<QSplitter *>(src->parentWidget());if(pPSplitter->count() > 1){QWidget *pBWidget = pPSplitter->widget(!pPSplitter->indexOf(src));QSplitter *pPPSplitter = qobject_cast<QSplitter *>(pPSplitter->parentWidget());if(nullptr == pPPSplitter){if(nullptr == qobject_cast<QSplitter *>(pBWidget)){delete src;return ;}else{this->layout()->addWidget(pBWidget);}}else{pPPSplitter->insertWidget(pPPSplitter->indexOf(pPSplitter),pBWidget);}}delete pPSplitter;qDebug()<<"开始打印剩余控件------------";recursiveInstallEventFilter(this);qDebug()<<"打印完成------------";
}void CSplitter::addWidget3(QWidget *dst, QWidget *src, Qt::Orientation orientation)
{if(!src)return ;if ((nullptr == dst) || (0 == this->layout()->count())){QSplitter *pSplitter = new QSplitter(orientation,this);pSplitter->addWidget(src);this->layout()->addWidget(pSplitter);}else{QSplitter *pPSplitter = qobject_cast<QSplitter *>(dst->parentWidget());if(orientation == pPSplitter->orientation()){qDebug()<<"+++++"<<dst->size()<<dst->baseSize()<<dst->sizePolicy()<<dst->sizeHint()<<dst->minimumSize()<<dst->maximumSize();qDebug()<<"+++++"<<src->size()<<src->baseSize()<<src->sizePolicy()<<src->sizeHint()<<src->minimumSize()<<src->maximumSize();pPSplitter->insertWidget(pPSplitter->indexOf(dst) + 1,src);for(int i = 0; i < pPSplitter->count(); i++){pPSplitter->setStretchFactor(i,1);}}else{QSplitter *pSplitter = new QSplitter(orientation,this);
//            pSplitter->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);pPSplitter->insertWidget(pPSplitter->indexOf(dst),pSplitter);qDebug()<<"-----"<<dst->size()<<dst->baseSize()<<dst->sizePolicy()<<dst->sizeHint()<<dst->minimumSize()<<dst->maximumSize();qDebug()<<"-----"<<src->size()<<src->baseSize()<<src->sizePolicy()<<src->sizeHint()<<src->minimumSize()<<src->maximumSize();//            dst->resize(0,0);
//            src->resize(0,0);pSplitter->addWidget(dst);pSplitter->addWidget(src);qDebug()<<"-----"<<dst->size()<<dst->baseSize()<<dst->sizePolicy()<<dst->sizeHint()<<dst->minimumSize()<<dst->maximumSize();qDebug()<<"-----"<<src->size()<<src->baseSize()<<src->sizePolicy()<<src->sizeHint()<<src->minimumSize()<<src->maximumSize();//            pSplitter->setStretchFactor(0,1);
//            pSplitter->setStretchFactor(1,1);}}}void CSplitter::removeWidget3(QWidget *src,bool clearEmptySplitter)
{if(!src || !src->parentWidget())return ;//清理空的Splitterif(clearEmptySplitter){QSplitter *pSrcSplitter = qobject_cast<QSplitter *>(src);if(pSrcSplitter){QWidget *parent = pSrcSplitter->parentWidget();if(0 == pSrcSplitter->count())delete pSrcSplitter;removeWidget3(parent,true);}}else{QSplitter *pPSplitter = qobject_cast<QSplitter *>(src->parentWidget());delete src;if(pPSplitter)removeWidget3(pPSplitter,true);//递归查找空的父Splitter 并删除}qDebug()<<"开始打印剩余控件------------";recursiveInstallEventFilter(this);qDebug()<<"打印完成------------";
}void CSplitter::recursiveInstallEventFilter(QObject *pObject)
{if(pObject->children().count() > 0) {foreach (QObject *objChild, pObject->children()) {qDebug()<<"子控件"<<objChild;recursiveInstallEventFilter(objChild);}}
}

CSplitter.h

#ifndef CSPLITTER_H
#define CSPLITTER_H#include <QWidget>
#include <QSplitter>class CSplitter : public QWidget
{Q_OBJECT
public:explicit CSplitter(QWidget *parent = 0);//第一种实现  这种实现在拆分的时候 可以1:1拆分void addWidget(QWidget *dst,QWidget *src,Qt::Orientation orientation);void removeWidget(QWidget *src);//第二种实现 减少Splitter的用量 降低内存开销  但是默认拆分不是1:1  各种设置试了但没成功void addWidget2(QWidget *dst,QWidget *src,Qt::Orientation orientation);void removeWidget2(QWidget *src);//第三种实现 最少的QSplitter使用 但是默认拆分不是1:1  各种设置试了但没成功void addWidget3(QWidget *dst,QWidget *src,Qt::Orientation orientation);void removeWidget3(QWidget *src, bool clearEmptySplitter = false);void recursiveInstallEventFilter(QObject *pObject);
};#endif // CSPLITTER_H

Qt 70行代码实现控件任意拆分 选中控件水平垂直拆分 窗口分割相关推荐

  1. 用70行代码实现日志分析程序​

    python又一力作,感受python的强大.用70行代码实现日志分析程序 功能介绍:可直接对文本日至进行分组和排序功能,完了输出结果粘贴到excel里就可以直接生成图表,对于排查一些生产环境问题有很 ...

  2. 爬取微信文章,用70行代码爬取了搜狗上666篇文章

    因为再看崔庆才的教程,刚好看到爬取微信文章,所以就想着自己试试.打开搜狗发现,搜狗的微信文章页面网页布局有了变化(准确来说是简单了一点). 所以分析了一下,用了70行代码实现了爬取上面['搞笑', ' ...

  3. 70行代码撸一个桌面自动翻译神器(采用Markdown格式编写)

    70行代码撸一个桌面自动翻译神器 前言 工作上经常需要与外国友人邮件沟通,奈何工作电脑没有安装有道词典一类的翻译软件,结合自己的需要,自己撸一个桌面翻译神器. 基本思路:基于PySimpleGUI开发 ...

  4. activex 控件的id 定义位置+使用ocx控件的客户端程序中对控件定义的文件中控件id定义的位置...

    activex 控件的id 定义位置 // SuperDisplayCtl.cpp IMPLEMENT_OLECREATE_EX(CSuperDisplayCtrl, "SuperDispl ...

  5. 用 70 行代码给你自己写一个 strace

    基本上任何使用了一段时间 Linux 的人,最后都会知道并爱上 strace 命令.strace 是系统调用跟踪器,它跟踪程序执行的进入内核以与外面的世界交互的调用.如果你还不熟悉这个令人惊奇的多才多 ...

  6. 开发者70行代码破解苹果OSX远程锁定安全功能

    苹果的 Mac OS X 有一项"Find My Mac"的防盗功能,开启这项功能后用户可以通过自己的 iOS 鼠标远程锁定 Mac 机器,只有输入正确的 4 位 PIN 后才能对 ...

  7. 70行代码实现同花顺,通达信,麦语言大部分技术指标公式

    MyTT是什么? MyTT将通达信,同花顺,文华麦语言等指标公式indicators,最简移植到Python中,核心库单个文件,仅百行代码,实现所有常见指标MACD,RSI,BOLL,ATR,KDJ, ...

  8. html table水平和垂直滚动条,Ajax: Excel风格的HTML Table输入控件[二]:外部表格与水平垂直滚动条...

    实际效果:  [url]http://www.weiqihome.com/scotttable.jsp[/url] 前一节介绍了内部表格的区域划分与区域标识,这一节介绍外部表格. 外部表格的作用是提供 ...

  9. Easyocr - 3行代码识别图片中的任意语言文字

    AI派在读学生小姐姐Beyonce Java实战项目练习群 长按识别下方二维码,按需求添加 扫码添加Beyonce小姐姐 扫码关注 进Java学习大礼包 今天给大家介绍一个超级简单且强大的OCR文本识 ...

  10. 【python】70行代码,实现 GTA侠盗猎车 按键组合触发 作弊码。附源码 及 效果图

    [python]实现GTA侠盗猎车通过按键组合触发作弊码 引言 实现效果 代码 源码下载链接 引言 众所周知,GTA中的作弊码不需要输入框. 只需要通过键盘输入特定的组合,即可触发效果. 实现效果 任 ...

最新文章

  1. ORM查询语言(OQL)简介--概念篇
  2. 堆的定义与操作(C语言)
  3. LDAP----manage-account
  4. 文章采集伪原创工具_伪原创文章技巧(如何提高伪原创文章的原创度)
  5. 详解HTML5网页结构
  6. ABP框架使用打印日志
  7. 如何手动安装wxpython_如何在Ubuntu中安装wxPython的方法及命令
  8. 使用userscript扩展浏览器插件
  9. Javascript中的prototype是什么
  10. java房屋出租预约看房系统springboot ssm带房东租客
  11. 上载人生(数字天堂)
  12. 中国浙江省动漫产业发展方向探析及投资决策建议报告2021-2027年
  13. 一页纸说清楚“什么是深度学习?”
  14. CAJ如何转化为PDF文件
  15. IDEA 支持vue
  16. k8s修改ingress命令
  17. 大一计算机ppt课程实训报告,大一计算机实训报告实用范文
  18. TiDB-unsafe recover(三台tikv宕机两台)
  19. 小哥自创AI防拖延系统,一玩手机就被“闪瞎” | Reddit高热
  20. BFT-DPoS共识算法讲解

热门文章

  1. vue学习笔记-6-样式绑定
  2. 计算机单机游戏c0005错误,堡垒之夜Epic Games Launcher错误怎么办错误解决方法介绍...
  3. Eclipse打开报错解决方案
  4. 卫生纸玫瑰花折法5步_手工教程:做一个漂亮的玫瑰花捧花,用折纸表达我喜欢你...
  5. linux用Vim上传.sql,真的有(很多)linux大牛用vim写项目吗?
  6. editplus 打开大文件_CorelDRAW文件损坏的几种解决方法
  7. mac无法正确打开html,苹果MacBook电脑打不开网页不能访问怎么办
  8. java一千_涨姿势:为什么Java中“1000=1000”为false,而”100=100“为true?
  9. Springboot的工作机制:1 Springboot初体验
  10. windows关闭被占用的端口