QGridLayout添加删除交换复制Widget
addWidget
QGridLayout中添加Widget最好统一使用带有行列值的addWidget版本,比如初始化时添加各个Widget:
KLineWidget* widget = new KLineWidget(50);
ui.gridLayout->addWidget(widget, 0, 0);
KLineWidget* widget2 = new KLineWidget(100);
ui.gridLayout->addWidget(widget2, 0, 1);
KLineWidget* widget3 = new KLineWidget(150);
ui.gridLayout->addWidget(widget3, 1, 0);
KLineWidget* widget4 = new KLineWidget(200);
ui.gridLayout->addWidget(widget4, 1, 1);
一旦用这种方式添加了Widget之后,GridLayout的行列值你可以认为就不变了,因为你可以读取QGridLayout的行列计数,并执行任意的removeWidget方法,都会发现QGridLayout的rowCount和colCount的值都不会改变。
原始界面
那是不是我们就无法删除一行删除一列甚至是删除一个Widget了呢?当然不是。我可以删除任意一个Widget,一行,一列。
这个里面QGridLayout在管理Grid里面的对象的时候将槽和对象分开的,槽就是行列数量,你可以认为addWidget的时候只会增加,removeWidget的时候不会减少。
删除一个对象
那我们如何删除一个对象呢?分两步。
第一步:在layout中得到这个对象,让其隐藏。比如setVisible(false)。如果你不把这个窗口隐藏,这个窗口一定会显示出来,哪怕他被layout->removeWidget()也一样会显示出来。
第二部:在layout中删除这个widget,执行
auto child = layout->itemAtPosition(0, 0);//准备获取对象
layout->removeWidget(child->widget());//删除layout中的对象
以上两步执行完之后,界面上的行列数不变,但是widget对应的窗口就不见了,这就已经实现了删除的功能。
这个时候你访问itemAtPosition(0,0)会得到一个空指针。
其实你想删除(0,0)对象,只需要调用一下widget的隐藏接口即可,只不过这时候itemAtPostion(0,0)不是空,还是那个widget。
删除第一行
这时候同上面删除一个对象一样,我们只需要将第一行的widget都隐藏即可
widget->setVisible(false);
widget2->setVisible(false);
界面会自动适应,将下面一行的放大填充到整个QGridLayout的区域,从而效果上就是删除了一行
删除一列是一样的,就不赘述了。
交互两个对象
由上面的分析可知,交互两个对象,就是交换两个widget而已,所以可以先保存两个widget,再删除,最后再addWidget即可。
下面交换左上角和右下角的两个对象
auto layout = ui.gridLayout;
//交互(0,0)和(1,1)
//先保存widget对象指针
auto child = layout->itemAtPosition(0, 0);
auto child4 = layout->itemAtPosition(1, 1);
KLineWidget* widget = static_cast<KLineWidget*>(child->widget());
KLineWidget* widget4 = static_cast<KLineWidget*>(child4->widget());
//1 先删除
layout->removeWidget(child->widget());
layout->removeWidget(child4->widget());
//2 再添加
ui.gridLayout->addWidget(widget, 1, 1);
ui.gridLayout->addWidget(widget4, 0, 0);
效果
交互一个widget对象
由于layout->removeWidget(widget)接口的存在,说明GridLayout在管理里面的窗口对象widget的时候其实是按照指针互斥的方式来实现的,指认widget的指针,那我们想让两个Grid共享一个窗口怎么办呢?我们只使用(row,col)接口可以吗?不可以。只能重新创建新的widget副本,再添加到对应的(row,col)中。
一个窗体widget只会有一个副本显示,哪怕你把他放到了多个gridye只会显示一个。
例如,我想把第一个widget,复制到右下角,结果,右下角并没有显示
auto layout = ui.gridLayout;
//交互(0,0)和(1,1)
//先保存widget对象指针
auto child = layout->itemAtPosition(0, 0);
auto child4 = layout->itemAtPosition(1, 1);
KLineWidget* widget = static_cast<KLineWidget*>(child->widget());
KLineWidget* widget4 = static_cast<KLineWidget*>(child4->widget());
//1 先删除
layout->removeWidget(child->widget());
layout->removeWidget(child4->widget());
widget4->setVisible(false);
//2 再添加
ui.gridLayout->addWidget(widget, 1, 1);
ui.gridLayout->addWidget(widget, 0, 0);
这时候我们的做法是重新设置目标widget用来显示的内容,而不是创建widget和删除widget,也不是复制widget的指针。