Qt窗口布局之合并与拖出

前言:

在某些应用场景中,我们可能期望窗口能够塞入已有的布局,又能脱离出来单独显示。
举个例子,你创建了五个窗口,你希望五个窗口既能塞入到一个窗口中布局,又想随时控制将单独一个窗口脱离出来,独立于原本的大窗口显示,如图:
在这里插入图片描述
在这里插入图片描述
这里尝试了两种方法,均能实现,但推荐第二种方法

二、前期准备

创建一个简单的QWidget工程,注意不要在ui界面中拖拽窗口控件,单纯用代码操作。不然可能会出现各种各样的问题。
这里只创建一些按钮,还有一个等待填充的大窗口
在这里插入图片描述
先创建一个水平布局,deleteAllitemsOfLayout是用来移除空间的(并不是删除),然后创建一个QWidget指针list。

    QHBoxLayout *hboxLayout = nullptr;
    void deleteAllitemsOfLayout(QLayout* layout);

    QList<QWidget *> widget_list;

初始化中初始五个按钮,并顺便填充颜色,方便之后的区别

for(int i = 1; i < 6; i++){
	QWidget *widget = new QWidget();
	widget_list.append(widget);
	widget->setStyleSheet(QString("background-color: rgb(%0, %1, %2);").arg(15*i).arg(48*i).arg(30*i));
	
	//无边框等窗口属性,经测试就算窗口塞入过大窗口中,重新拿出来还是无边框的,不需要重新再设置
	//widget->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
    }

void MainWidget::deleteAllitemsOfLayout(QLayout *layout)
{
    if(!layout)
        return;
    QLayoutItem *child;
    //takeAt是将控件移出布局,如果需要对控件销毁,建议在外部对相关指针操作
    while ((child = layout->takeAt(0)) != nullptr)
    {
    }
}

三、方法一

通过删除hboxLayout的方式,重新创建布局

//移出
void MainWidget::on_pushButton_clicked()
{
	//移除控件并删除布局
    deleteAllitemsOfLayout(hboxLayout);
    if(hboxLayout){
        delete hboxLayout;
        hboxLayout = nullptr;
    }

    if(!hboxLayout){
    	//创建布局
        hboxLayout = new QHBoxLayout();
        //将除去最后一个窗口的其他窗口,塞入大窗口
        for(int i = 0; i < widget_list.count()-1; i++){
            hboxLayout->addWidget(widget_list[i]);
        }
        //给大窗口设置布局
        ui->widget->setLayout(hboxLayout);
		
		//对最后的窗口设置父类指针,如果不重新设置,它就还维持在上一次的设置中,还在大窗口里面
        widget_list.last()->setParent(nullptr);
        widget_list.last()->move(0,0);
        widget_list.last()->show();
    }
}
//合并
void MainWidget::on_pushButton_2_clicked()
{
	//移除控件并删除布局
    deleteAllitemsOfLayout(hboxLayout);
    if(hboxLayout){
        delete hboxLayout;
        hboxLayout = nullptr;
    }

    if(!hboxLayout){
    	//创建布局
        hboxLayout = new QHBoxLayout();
        //全部窗口都塞进大窗口
        for(int i = 0; i < widget_list.count(); i++){
            hboxLayout->addWidget(widget_list[i]);
        }
        ui->widget->setLayout(hboxLayout);
    }
}

四、方法二

尝试不删除hboxLayout ,发现也一样可以做到

	//首先,要在初始化时创建一个布局,并设置好
	hboxLayout = new QHBoxLayout();
    ui->widget->setLayout(hboxLayout);

void MainWidget::on_pushButton_3_clicked()
{
    deleteAllitemsOfLayout(hboxLayout);
    //要记得,将所有塞入过大窗口的窗口控件都设置一下父指针
    for(int i = 0; i < widget_list.count(); i++){
        widget_list[i]->setParent(nullptr);
    }

    if(hboxLayout){
        for(int i = 0; i < widget_list.count()-1; i++){
            hboxLayout->addWidget(widget_list[i]);
        }
        widget_list.last()->move(0,0);
        widget_list.last()->show();
    }
}

void MainWidget::on_pushButton_4_clicked()
{
    deleteAllitemsOfLayout(hboxLayout);

    for(int i = 0; i < widget_list.count(); i++){
        widget_list[i]->setParent(nullptr);
    }

    if(hboxLayout){
        for(int i = 0; i < widget_list.count(); i++){
            hboxLayout->addWidget(widget_list[i]);
        }
    }
}

五、总结

一开始执着于删除hboxLayout ,其实是怕控件会残留在里面什么的。这方面如果你不清楚布局和窗口之间的布局,其实还挺让人头疼的。比如你不设置父指针为空,你就会卡在为什么不能将它移出大窗口的烦恼中,明明我已经将控件移出布局了啊。那肯定就涉及一个概念,控件置于窗口之中,当然将窗口视作父窗口了,这在你加入布局的那一刻就决定了,即便移出布局,父窗指针还是保存的。
说的有点啰嗦了,不过只要按照这种方法,就能实现窗口的移出和合并,好像还有Dock Widget的方法,但还不太明白,好像直接拖拽就能拖出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值