Qt Dynamic QSplitter 动态分栏

13 篇文章 1 订阅
13 篇文章 0 订阅

动态增加分栏

本篇模拟Qt代码编辑器中的动态分栏功能,动态创建回收QSplitter

Qt_Dynamic_QSplitter

//mainwindow.cpp
MainWindow(){
	QSplitter *sp = new QSplitter(this);
	Widget     *w = new Widget(sp);
	sp->setHandleWidth(1);
	sp->setChildrenCollapsible(false);
	sp->addWidget(w);
	setCentralWidget(sp);
	resize(600,500);
}
//widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QSplitter>
#include <QComboBox>
#include <QStringListModel>
#include <QToolButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QResizeEvent>

#define ICONSIZE 20

class MyBtn: public QToolButton {
public:
    MyBtn(QString icon,QLayout *layout, QWidget *parent): QToolButton{parent}{
        setIcon(QIcon(icon)); setAutoRaise(true);
        setFixedSize(ICONSIZE,ICONSIZE); layout->addWidget(this);
    }
};

class Widget;
class WidgetPrivate: public QWidget{
public:
    explicit WidgetPrivate(QWidget *parent= nullptr);
protected:
    bool eventFilter(QObject *watched, QEvent *e) override;
private:
    QStringListModel *model;
    QComboBox *combox;
    MyBtn   *btnClose;
    MyBtn  *btnSplitV;
    MyBtn  *btnSplitH;
    friend     Widget;
};

class Widget: public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = nullptr);
protected:
    virtual void resizeEvent(QResizeEvent *e) override;
protected slots:
    void slot_Split(QObject *sender, Qt::Orientation orient);
    void slot_UnSplit(QObject *sender);
private:
    WidgetPrivate  *d_ptr;
};

#endif // WIDGET_H
//widget.cpp
#include "testwidget.h"

WidgetPrivate::WidgetPrivate(QWidget *parent): QWidget{parent}
{
    parent->installEventFilter(this);
    QVBoxLayout *vlayout = new QVBoxLayout(this);
    QHBoxLayout *hlayout = new QHBoxLayout();
    hlayout->setContentsMargins(0,0,0,0);hlayout->setSpacing(1);
    vlayout->setContentsMargins(0,0,0,0);vlayout->setSpacing(0);
    QStringListModel *model = new QStringListModel({"<no document>"},this);
    combox = new QComboBox(this); combox->setFixedHeight(ICONSIZE);
    combox->setModel(model) ;hlayout->addWidget(combox);
    btnSplitV = new MyBtn(":/split_v.svg",hlayout,this);
    btnSplitH = new MyBtn(":/split_h.svg",hlayout,this);
    btnClose  = new MyBtn(":/close.svg",  hlayout,this);
    vlayout->addLayout(hlayout);
    //QTextEdit *t=new QTextEdit(this);t->setStyleSheet("border:none;");vlayout->addWidget(t);
}

//auto-hide
bool WidgetPrivate::eventFilter(QObject *watched, QEvent *e)
{   //need parent->installEventFilter
    if     ( e->type()==QEvent::Enter ){ this->show(); return true;}
    else if( e->type()==QEvent::Leave ){ this->hide(); return true;}
    else return QObject::eventFilter(watched, e);
}

Widget::Widget(QWidget *parent): QWidget{parent}
{
    d_ptr = new WidgetPrivate(this);
    connect(d_ptr->btnSplitV,&QToolButton::clicked,this,[=](){slot_Split(this,Qt::Vertical);});
    connect(d_ptr->btnSplitH,&QToolButton::clicked,this,[=](){slot_Split(this,Qt::Horizontal); });
    connect(d_ptr->btnClose, &QToolButton::clicked,this,[=](){slot_UnSplit(this); });
    setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
}

void Widget::resizeEvent(QResizeEvent *e)
{
    d_ptr->resize(e->size().width(), d_ptr->height());
    QWidget::resizeEvent(e);
}

void Widget::slot_Split(QObject *sender, Qt::Orientation orient)
{
    QSplitter *parent_sp = qobject_cast<QSplitter*>(sender->parent() );
    if(!parent_sp)return;

    //1) add new splitter
    QSplitter *subSP = new QSplitter(this);
    subSP->setHandleWidth(1);
    subSP->setOrientation(orient);
    subSP->setChildrenCollapsible(false);

    //2) old splitter add this new splitter as its child
    int index = parent_sp->indexOf(this);
    parent_sp->insertWidget(index,subSP);

    //3) new splitter add parent's child
    this->setParent(subSP);
    subSP->addWidget(this);

    //4) new splitter add a new widget
    Widget* testW = new Widget(subSP);
    subSP->addWidget(testW);
}

void Widget::slot_UnSplit(QObject *sender)
{
    QSplitter *parent_sp = qobject_cast<QSplitter*>(sender->parent() );
    if(!parent_sp) return;
    // if("MainWindow" == parent_sp->parent()->objectName()) return; //keep the last one

    // move sibline to parent before delete this widget and sub-splitter  
    int index = parent_sp->indexOf(this);
    QWidget *sibline = parent_sp->widget(!index);
    QSplitter *sp=(QSplitter*)parent_sp->parent();
    if(sibline && sp){
        index = sp->indexOf(parent_sp);
        sp->replaceWidget(index,sibline);
        sibline->setParent(sp);
    }
    //delete
    parent_sp->deleteLater();
    this->deleteLater();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值