2010-10-15 27 views
13

Tôi đang sử dụng hàm tạo QWidget(QWidget *parent). Widget phụ huynh này chứa rất nhiều widget con. Tôi cần phải xóa tất cả các widget con từ cha mẹ khi chạy. Tôi có thể làm cái này như thế nào?Làm thế nào để xóa tất cả các Widgets trong Widget phụ huynh?

+0

Câu trả lời cho câu hỏi http://stackoverflow.com/questions/4272196/qt-remove-all-widgets-from-layout/18496300#18496300 có thể có liên quan. –

Trả lời

-6

Bạn có thể sử dụng sau đây trong lớp phụ tùng cha mẹ của bạn:

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

Cảm ơn. nó hoạt động hoàn hảo. Chính xác tôi cần điều này. – saravanan

+9

Ngoài ra còn có một chức năng được cung cấp bởi Qt gọi là qDeleteAll, trong đó có một container và xóa tất cả các mục trong container. Vì vậy, bạn có thể đơn giản hóa điều này để qDeleteAll (findChildren ()); –

+3

nếu có rất nhiều trẻ em, bạn cũng có thể cân nhắc setUpdatesEnabled (false); qDeleteAll (findChildren ()); setUpdatesEnabled (đúng); – MadH

20

câu trả lời trước là sai !! Bạn không thể sử dụng findChildren để xóa con của tiện ích con, vì số findChildrenđệ quy của chúng tôi liệt kê trẻ em. Do đó, bạn sẽ xóa trẻ em của trẻ em, sau đó có thể bị xóa hai lần, có khả năng làm hỏng ứng dụng của bạn.

Nói chung, trong Qt, lấy danh sách các con trỏ QObject và xóa từng con một là nguy hiểm, vì phá hủy một đối tượng có thể phá hủy các đối tượng khác, do cơ chế sở hữu gốc hoặc bằng cách kết nối tín hiệu destroyed() một khe cắm deleteLater(). Do đó, phá hủy các đối tượng đầu tiên trong danh sách có thể làm mất hiệu lực các đối tượng tiếp theo.

Bạn cần phải liệt kê trẻ em widget bằng cách:

  • Đi qua cờ Qt :: FindDirectChildrenOnly để findChild nếu bạn đang sử dụng Qt5 (mà không tồn tại khi câu hỏi được hỏi ...)
  • Sử dụng các chức năng QLayout để liệt kê các mục,
  • Sử dụng QObject :: trẻ em và cho mỗi thử nghiệm nếu nó là một tiện ích con sử dụng isWidgetType() hoặc một diễn viên
  • Sử dụng findChild() trong một vòng lặp và xóa kết quả cho đến khi nó trả về con trỏ rỗng
+0

^^ câu trả lời đúng – rfcoder89

+3

Bạn cũng có thể sử dụng 'Qt :: FindDirectChildrenOnly' trên' findChildren' để tránh việc xóa hai lần –

+0

@DrewMcGowen: true, nhưng chỉ từ Qt5 – galinette

11

Để chăm sóc của vấn đề đệ quy chỉ ra bởi @galinette bạn chỉ có thể loại bỏ các vật dụng trong một vòng lặp while

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

Đây là câu trả lời phù hợp nhất theo ý kiến ​​của tôi – Michal

5

Từ Qt docs

Đoạn mã sau đây cho thấy một cách an toàn để loại bỏ tất cả các mục từ một bố cục:

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

Tổng hợp và bổ sung:

.210

Đối Qt5 trong một dòng:

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

Đối Qt5 cho rất nhiều trẻ em, sử dụng setUpdatesEnabled():

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

Lưu ý rằng đây không phải là ngoại lệ an toàn! Trong khi Qt không vào thời điểm này xuất hiện để ném ngoại lệ ở đây, các tín hiệu bị phá hủy() có thể được kết nối với mã mà ném, hoặc một đối tượng bị ghi đè :: childEvent (QChildEvent *) có thể ném.

Better sẽ được sử dụng một lớp helper:

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

Đối Qt4:

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

Loại bỏ từ QLayout làm việc trong cả hai Qt4 và Qt5:

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

QObject s (và do đó QWidgets) loại bỏ mình (automagically) từ cha mẹ của họ trong (QObject) destructor của họ.

Các vấn đề liên quan