2010-10-15 158 views
13

我正在使用構造函數QWidget(QWidget *parent)。這個父窗口小部件包含很多子窗口小部件。我需要在運行時從父級清除所有子部件。我怎樣才能做到這一點?如何清除父窗口小部件中的所有窗口小部件?

+0

問題的答案http://stackoverflow.com/questions/4272196/qt-remove-all-widgets-from-layout/18496300#18496300可能是相關的。 – 2013-08-28 19:15:31

回答

-6

您可以使用您的父控件類以下內容:

QList<QWidget *> widgets = findChildren<QWidget *>(); 
foreach(QWidget * widget, widgets) 
{ 
    delete widget; 
} 
+0

謝謝。它的工作完美。我確實需要這個。 – saravanan 2010-10-15 08:18:37

+9

Qt還提供了一個名爲qDeleteAll的函數,它接收容器並刪除容器中的每個項目。所以你可以簡化這個qDeleteAll(findChildren ()); – 2010-10-15 18:23:05

+3

如果有孩子的LOTS,你也可以考慮setUpdatesEnabled(false); qDeleteAll(findChildren ()); setUpdatesEnabled(真); – MadH 2010-11-26 14:26:18

20

以前的答案是錯的!您不能使用findChildren刪除小部件的子項,因爲Qt4的findChildren遞歸列出子項。因此,您將刪除可能會被刪除兩次的兒童,這可能會導致應用程序崩潰。

更一般地,在Qt中,服用的QObject指針的列表,並通過一個刪除它們一個是危險的,因爲破壞對象可以鏈破壞其它的目的,由於父所有權機制,或通過destroyed()信號連接到一個deleteLater()插槽。因此,銷燬列表中的第一個對象可能會使下一個對象失效。

你需要列出孩子要麼通過小部件:

  • 傳遞了Qt :: FindDirectChildrenOnly標誌,如果你正在使用QT5到findChild(當有人問並不存在...)
  • 使用QLayout函數列出項目,
  • 使用QObject :: children,並且對於每個測試,如果它是使用isWidgetType()或者演員組件的widget,空指針
+0

^^正確的答案 – rfcoder89 2014-05-22 12:48:00

+3

您也可以在'findChildren'上使用'Qt :: FindDirectChildrenOnly'來避免雙重刪除 – 2015-03-18 15:23:48

+0

@DrewMcGowen:true,但只有自Qt5 – galinette 2015-03-29 19:09:11

11

照顧遞歸性問題,指出了@galinette你可以只取出部件在while循環

while (QWidget* w = findChild<QWidget*>()) 
    delete w; 
+1

這是我看來最合適的答案 – Michal 2015-02-18 08:40:26

5

從Qt的docs

下面的代碼片段展示了一個安全的方式來從佈局中刪除所有項目:

QLayoutItem *child; 
while ((child = layout->takeAt(0)) != 0) { 
    ... 
    delete child; 
} 
3

總結和補充:

對於QT5在一條線:

qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly)); 

對於QT5了很多孩子,使用setUpdatesEnabled():

parentWidget->setUpdatesEnabled(false); 
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly)); 
parentWidget->setUpdatesEnabled(true); 

請注意,這不是異常安全的!雖然Qt此時並不會在這裏拋出異常,但destroy()的信號可能會連接到拋出的代碼,或者被覆蓋的Object :: childEvent(QChildEvent *)可能拋出。

更好的辦法是使用一個輔助類:

class UpdatesEnabledHelper 
{ 
    QWidget* m_parentWidget; 
public: 
    UpdatesEnabledHelper(QWidget* parentWidget) : m_parentWidget(parentWidget) { parentWidget->setUpdatesEnabled(false); } 
    ~UpdatesEnabledHelper() { m_parentWidget->setUpdatesEnabled(true); } 
}; 

...

UpdatesEnabledHelper helper(parentWidget); 
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly)); 

對於的Qt4:

QList<QWidget*> childWidgets = parentWidget->findChildren<QWidget*>(); 
foreach(QWidget* widget, childWidgets) 
    if (widget->parentWidget() == parentWidget) 
     delete widget; 

從QLayout刪除工作在兩個的Qt4和QT5:

QLayoutItem* child; 
while (NULL != (child = layout->takeAt(0))) // or nullptr instead of NULL 
    delete child; 

的QObject s(因此QWidgets)會從它們的(QObject)析構函數中的父級中刪除它們(自動)。

相關問題