清除Qt中的布局

rcv*_*rcv 12 c++ qt qt4

我正在Qt中创建一个应用程序,允许用户在QGraphicsView中拖动各种"模块".每当选择其中一个模块时,它会发出一个信号,然后由"ConfigurationWidget"拾取,这是一个侧面板,应该显示所选模块的所有相关参数:

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
    }
};
Run Code Online (Sandbox Code Playgroud)

问题是当选择模块时,ConfigurationWidget实际上永远不会被清除.新字段只是绘制在旧字段上.我尝试过hide()和show(),invalidate(),update()等各种组合无济于事.

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

Wes*_*ker 29

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这对你有所帮助!

  • 您不需要`if(item-> widget())`。删除“ NULL”是不可行的。 (3认同)
  • ASAN 在 `if (item->widget())` 处给我一个堆释放后使用错误。 (3认同)
  • 我添加`if(QSpacerItem*SpacerItem = Item-> spacerItem()){delete SpacerItem; 那个也是那个:) (2认同)
  • 导致错误的@sjwarner:`item->spacerItem()` 本质上是`return dynamic_cast<QSpacerItem*>(item)`。即你会双重释放那块内存。注意:我仅凭经验知道这一点。 (2认同)

ale*_*sdm 9

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

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
}
Run Code Online (Sandbox Code Playgroud)

  • 这同样是疯狂的丑陋和疯狂的聪明.;)谢谢你分享这个黑客.我希望有'QLayout :: clear()`... (4认同)

rcv*_*rcv 6

看起来最好的方法是使用 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);
}
Run Code Online (Sandbox Code Playgroud)

  • 使用 QObject 派生类时,应使用 qobject_cast 而不是 dynamic_cast:http://doc.qt.nokia.com/latest/qobject.html#qobject_cast (4认同)