繁体   English   中英

清除 Qt 中的布局

[英]Clearing a Layout in Qt

我正在 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
    }
};

问题是,在选择模块时,ConfigrationWidget从未实际清除。 新字段只是在旧字段上绘制。 我尝试了 hide() 和 show()、invalidate()、update() 等的各种组合,但都无济于事。

制作可以动态更改其字段的小部件的正确方法是什么?

我之前用过的代码循环如下:

void clearLayout(QLayout *layout) {
    if (layout == NULL)
        return;
    QLayoutItem *item;
    while((item = layout->takeAt(0))) {
        if (item->layout()) {
            clearLayout(item->layout());
            delete item->layout();
        }
        if (item->widget()) {
           delete item->widget();
        }
        delete item;
    }
}

希望这对你有帮助!

如果您将布局转移到堆栈上分配的另一个小部件,则该布局中的小部件将成为新小部件的子部件。 当临时对象超出范围时,它会自动破坏布局和其中的所有小部件。

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
}

看起来最好的方法是使用 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);
}

我最近在使用 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;
}

使用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;
        }
    }
}

当您希望它们从窗口中消失时,将这些项目重新设置为 NULL。 我最近遇到了类似的问题,重新养育解决了这些问题。

到目前为止,我没有发现其他任何答案都有效。 它们要么崩溃,要么没有完全清除布局。 所以这是我发现的工作,我希望其他人觉得这很有用。

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;
    }
}

感谢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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM