前言:
在某些应用场景中,我们可能期望窗口能够塞入已有的布局,又能脱离出来单独显示。
举个例子,你创建了五个窗口,你希望五个窗口既能塞入到一个窗口中布局,又想随时控制将单独一个窗口脱离出来,独立于原本的大窗口显示,如图:
这里尝试了两种方法,均能实现,但推荐第二种方法
二、前期准备
创建一个简单的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的方法,但还不太明白,好像直接拖拽就能拖出来。