2011-09-15 17 views
8

Tôi đã viết một lớp dẫn xuất từ ​​QGraphicsScene. Tại một thời điểm tôi cần phải loại bỏ tất cả các mục từ hiện trường và tôi muốn các mục bị phá hủy vật lý (destructor gọi là). Tôi đã thử những điều sau đây:Cách xóa tất cả QGraphicsItem khỏi QGraphicsScene

QList<QGraphicsItem*> all = items(); 
for (int i = 0; i < all.size(); i++) 
{ 
    QGraphicsItem *gi = all[i]; 
    removeItem(gi); 
    delete gi; // warning at this line 
} 

Qt Creator phát hiện cảnh báo: C4150: xóa con trỏ thành loại không đầy đủ 'QGraphicsItem'; không có destructor gọi là

Tôi không chắc tại sao lại như thế. QGraphicsItem có trình phá hủy ảo nên các mục sẽ bị xóa khỏi bộ nhớ.

Nếu đây không phải là cách phù hợp, làm thế nào tôi có thể xóa tất cả QGraphicsItem s từ QGraphicsScene? Lưu ý rằng tôi biết khi nào cảnh bị xóa, tất cả các mục cũng sẽ bị xóa. Nhưng tôi muốn xóa các mục khỏi cảnh và vẽ các mục khác. Tôi muốn xóa các mục đã xóa khỏi bộ nhớ.

Trả lời

7

Bạn phải

#include <QGraphicsItem> 

trong tập tin đó. Nếu không, trình biên dịch không biết gì là QGraphicsItem là, nó có một destructor ảo, vv

9

Giống như jpalecek chỉ ra, bạn đang thiếu tệp tiêu đề. Bạn nên chấp nhận câu trả lời của mình. Tôi sẽ chỉ ra hai vấn đề tiềm ẩn:

Trước hết, bạn không cần phải gọi số QGraphicsScene::removeItem(). QGraphicsItem::~QGraphicsItem() thực hiện điều đó cho bạn.

Thứ hai. Hãy cẩn thận nếu bạn đặt bất kỳ QGraphicsItem bên trong của người khác. Đó là, bạn có các vật phẩm là trẻ em của các vật dụng khác. Các destructor của QGraphicsItem tự động xóa tất cả các con của nó. Vì vậy, khi bạn lặp lại các mục được trả lại từ QGraphicsScene, bạn có thể sẽ xóa mục con đã bị cha mẹ xóa. Ví dụ: giả sử bạn có 2 mục, A và B và B là con của A. Khi bạn xóa A, B sẽ bị xóa tự động. Và sau đó bạn đến B và cố gắng xóa nó. BOOM!

Một cách an toàn hơn để làm điều này là để kiểm tra nếu tài liệu là cấp cao nhất một, tức là nó không có cha mẹ:

QList<QGraphicsItem*> all = items(); 
for (int i = 0; i < all.size(); i++) 
{ 
    QGraphicsItem *gi = all[i]; 
    if(gi->parentItem()==NULL) { 
     delete gi; 
    } 
}