C++ 清除 Qt 中的布局
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4857188/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Clearing a Layout in Qt
提问by rcv
I'm creating an application in Qt that allows users to drag around various "modules" in a QGraphicsView. Whenever one of these modules is selected, it emits a signal which is then picked up by a "ConfigurationWidget" which is a side-panel which should display all of the relevant parameters of the selected module:
我正在 Qt 中创建一个应用程序,它允许用户在 QGraphicsView 中拖动各种“模块”。Whenever one of these modules is selected, it emits a signal which is then picked up by a "ConfigurationWidget" which is a side-panel which should display all of the relevant parameters of the selected module:
class ConfigurationWidget : public QWidget
{
Q_OBJECT
public:
ConfigurationWidget(QWidget *parent) : QWidget(parent) {}
public slots:
void moduleSelected(Module* m)
{
if(layout())
{
while (itsLayout->count()>0)
{
delete itsLayout->takeAt(0);
}
}
delete layout();
itsLayout = new QFormLayout(this);
itsLayout->addRow(QString(tr("Type:")), new QLabel(m->name()));
itsLayout->addRow(QString(tr("Instance:")), new QLabel(m->instanceID()));
// ... Display a whole bunch of other fields that depends on the module
}
};
The problem is that the ConfigurationWidget never actually gets cleared when a module is selected. The new fields are just drawn over the old ones. I've tried various combinations of hide() and show(), invalidate(), update(), etc. to no avail.
问题是,在选择模块时,ConfigrationWidget从未实际清除。新字段只是在旧字段上绘制。我尝试了 hide() 和 show()、invalidate()、update() 等的各种组合,但都无济于事。
What's the correct way to make a widget that can change its fields like this on the fly?
制作可以动态更改其字段的小部件的正确方法是什么?
采纳答案by rcv
It looks like the best way to do this is to use a QStackedLayout, as hinted at by armonge:
看起来最好的方法是使用 QStackedLayout,正如 armonge 所暗示的那样:
void ConfigurationWidget::moduleSelectedSlot(Module* m)
{
QStackedLayout *stackedLayout = qobject_cast<QStackedLayout*>(layout());
QWidget *layoutWidget = new QWidget(this);
QFormLayout *formLayout = new QFormLayout(layoutWidget);
formLayout->addRow(QString(tr("Type:")), new QLabel(m->name()));
formLayout->addRow(QString(tr("Instance:")), new QLabel(m->instanceID()));
// ... Display a whole bunch of other fields that depends on the module
delete stackedLayout->currentWidget();
stackedLayout->addWidget(layoutWidget);
stackedLayout->setCurrentWidget(layoutWidget);
}
回答by Wes Hardaker
The code loop I've used before is as follows:
我之前用过的代码循环如下:
void clearLayout(QLayout *layout) {
QLayoutItem *item;
while((item = layout->takeAt(0))) {
if (item->layout()) {
clearLayout(item->layout());
delete item->layout();
}
if (item->widget()) {
delete item->widget();
}
delete item;
}
}
Hopefully that will be helpful to you!
希望这对你有帮助!
回答by alexisdm
If you transfer the layout to another widget allocated on the stack, the widgets in that layout become the children of the new widget. When the temporary object goes out of scope it destroys automatically the layout and all the widgets in it.
如果您将布局转移到堆栈上分配的另一个小部件,则该布局中的小部件将成为新小部件的子部件。当临时对象超出范围时,它会自动破坏布局和其中的所有小部件。
void moduleSelected(Module* m)
{
if(layout())
QWidget().setLayout(layout());
itsLayout = new QFormLayout(this);
itsLayout->addRow(QString(tr("Type:")), new QLabel(m->name()));
itsLayout->addRow(QString(tr("Instance:")), new QLabel(m->instanceID()));
// ... Display a whole bunch of other fields that depends on the module
}
回答by Dorian
Using while((item = layout->takeAt(0)))
will cause warning message "Invalid index take at 0".
I use count()
instead
使用while((item = layout->takeAt(0)))
将导致警告消息“无效索引采用 0”。我用count()
,而不是
void clearLayout(QLayout *layout)
{
if (layout) {
while(layout->count() > 0){
QLayoutItem *item = layout->takeAt(0);
QWidget* widget = item->widget();
if(widget)
delete widget;
delete item;
}
}
}
回答by nyu
Reparent the items to NULL when you want them to disappear from a window. I had similar problems recently and reparenting solved them.
当您希望它们从窗口中消失时,将这些项目重新设置为 NULL。我最近遇到了类似的问题,重新养育解决了这些问题。
回答by David Casper
I have found none of the other answers so far work. They either crash or don't clear the layout completely. So here is what I have found to work, I hope others find this useful.
到目前为止,我没有发现其他任何答案都有效。它们要么崩溃,要么没有完全清除布局。所以这是我发现的工作,我希望其他人觉得这很有用。
void eraseLayout(QLayout * layout)
{
while(layout->count() > 0)
{
QLayoutItem *item = layout->takeAt(0);
QWidget* widget = item->widget();
if(widget)
{
delete widget;
}
else
{
QLayout * layout = item->layout();
if (layout)
{
eraseLayout(layout);
}
else
{
QSpacerItem * si = item->spacerItem();
if (si)
{
delete si;
}
}
}
delete item;
}
}
回答by Kádi
I recently run into the same problem with a QFormLayout. What worked for me (and is also in Qt's documentation: http://qt-project.org/doc/qt-5/layout.html) was the takeAt(int) method.
我最近在使用 QFormLayout 时遇到了同样的问题。对我有用的(也在 Qt 的文档中:http: //qt-project.org/doc/qt-5/layout.html)是 takeAt(int) 方法。
void clearLayout(QLayout *layout)
{
QLayoutItem *item;
while ((item = layout->takeAt(0)))
delete item;
}
回答by Theo
Thanks to Vaidotas Strazdas's commentary, I found my solution to reset a layout properly. Using the deleteLater()
method works very good, otherwise the delete
keyword causes massive display errors in the refreshed layout.
感谢Vaidotas Strazdas 的评论,我找到了正确重置布局的解决方案。使用该deleteLater()
方法效果很好,否则该delete
关键字会在刷新的布局中导致大量显示错误。
void resetLayout(QLayout* apLayout)
{
QLayoutItem *vpItem;
while ((vpItem = apLayout->takeAt(0)) != 0) {
if (vpItem->layout()) {
resetLayout(vpItem->layout());
vpItem->layout()->deleteLater();
}
if (vpItem->widget()) {
vpItem->widget()->deleteLater();
}
delete vpItem;
}
}