2011-01-31 77 views
12

我在Qt中創建了一個允許用戶在QGraphicsView中拖動各種「模塊」的應用程序。只要選擇這些模塊中的一個,它發出的信號,然後由一個「ConfigurationWidget」,這是一個側面面板,其應顯示所有選擇的模塊的相關參數的拾起:在Qt中清除佈局

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

問題當選擇模塊時ConfigurationWidget從未真正被清除。新的領域只是在舊的領域。我嘗試過hide()和show(),invalidate(),update()等各種組合,無濟於事。

什麼是正確的方式來使一個小部件,可以改變它的領域像這樣在飛行中?

+2

你應該使用QStackedWidget – armonge 2011-01-31 23:16:32

回答

4

它看起來像要做到這一點的最好辦法是使用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); 
} 
+4

當使用QObject的派生類,你應該使用qobject_cast的dynamic_cast的:http://doc.qt.nokia.com/latest/qobject.html#qobject_cast – 2011-02-01 07:38:45

+0

@PatriceBernassola:固定。 – rcv 2014-12-05 02:42:58

23

我以前使用的代碼迴路如下:

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

希望這會對你有所幫助!

+2

我會加`if(QSpacerItem * SpacerItem = Item-> spacerItem()){刪除SpacerItem; }`以及:) – sjwarner 2011-10-20 13:49:52

+0

進一步的調查還表明`刪除項目`是不必要的,因爲Qt爲我們處理(使用`Qlayout :: count()`來驗證) – sjwarner 2011-10-20 13:57:56

+1

你不需要`if(用品 - >插件())`。刪除NULL是一個nop。 – Timmmm 2012-12-09 15:11:49

8

如果您將佈局轉移到堆棧中分配的另一個小部件,則該佈局中的小部件將成爲新小部件的子項。當臨時對象超出範圍時,它會自動銷燬其中的佈局和所有小部件。

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

我最近遇到了與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; 
} 
1

使用while((item = layout->takeAt(0)))將導致警告消息「Invalid index take at 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; 
     } 
    } 
} 
0

重新設置父級的項目爲NULL,當你希望他們從窗口消失。最近我有類似的問題,重新解決它們。