2012-03-28 41 views
17

Tôi đang cố gắng xóa tiện ích con Qt khỏi bố cục trong ứng dụng PySide.PySide: Xóa tiện ích khỏi bố cục

Dưới đây là ví dụ tối thiểu. Nó là một tiện ích với 5 nút trong nó, và một trong những trung được cho là để loại bỏ bản thân khi nhấp:

What actually happens

Nút là không thể nhấp vào và rõ ràng:

import sys 
from PySide import QtGui 

app = QtGui.QApplication(sys.argv) 
widget = QtGui.QWidget() 
layout = QtGui.QVBoxLayout() 
buttons = [QtGui.QPushButton(str(x)) for x in xrange(5)] 

def deleteButton(): 
    b = layout.takeAt(2) 
    buttons.pop(2) 
    del b 
buttons[2].clicked.connect(deleteButton) 

map(layout.addWidget, buttons) 
widget.setLayout(layout) 
widget.show() 
app.exec_() 

Điều gì thực sự xảy ra đây là không được xem xét cho các tính toán bố cục, nhưng hình ảnh của nó vẫn được giữ nguyên.

Theo Qt documentation, đúng cách xóa tất cả các đối tượng từ một bố trí là:

while ((child = layout->takeAt(0)) != 0) { 
    delete child; 
} 

Ở đây tôi chỉ muốn xóa nút thứ ba, vì vậy tôi chỉ cần gọi takeAt(2), và sau đó del b để gọi destructor trên mục đó. Đối tượng nút cũng là .pop 'd từ danh sách buttons để đảm bảo không có tham chiếu còn sót lại cho đối tượng. Mã của tôi khác với mã trong tài liệu Qt có thể gây ra hành vi như thế nào?

+5

Tôi chỉ muốn chúc mừng bạn về một câu hỏi được hình thành thực sự tốt. Gần đây tôi đã thấy rất nhiều điều đơn giản chỉ là một vài câu không có ngữ cảnh, hoặc, một số lượng lớn mã mà chúng tôi dự kiến ​​sẽ đọc. Điều này có một vấn đề rất rõ ràng, cùng với một ví dụ mã rất ngắn gọn và chạy được. Hình ảnh của bạn cũng làm rõ vấn đề hơn nữa. Và bạn cho thấy những gì bạn đã thử. Bravo! – jdi

Trả lời

28

sửa chữa siêu đơn giản:

def deleteButton(): 
    b = layout.takeAt(2) 
    buttons.pop(2) 
    b.widget().deleteLater() 

Trước tiên, bạn phải chắc chắn rằng bạn đang giải quyết các nút thực tế và không phải là QWidgetItem được trả về từ cách bố trí, và sau đó gọi deleteLater() mà sẽ nói với Qt để tiêu diệt tiện ích sau khi vị trí này kết thúc và kiểm soát trở lại vòng lặp sự kiện.

Ví dụ khác minh họa tại sao sự cố xảy ra. Mặc dù bạn có mục bố cục, nhưng tiện ích cơ bản vẫn được chia nhỏ với tiện ích bố cục ban đầu.

def deleteButton(): 
    b = layout.takeAt(2) 
    buttons.pop(2) 
    w = b.widget() 
    w.setParent(None) 

Đây không phải là cách ưa thích, vì nó vẫn còn để dọn dẹp đối tượng không rõ ràng. Nhưng nó cho thấy rằng việc xóa phụ huynh cho phép nó rời khỏi màn hình hiển thị trực quan. Sử dụng deleteLater(). Nó làm sạch mọi thứ đúng cách.

+0

Tuyệt vời, cảm ơn ~ Tóc của tôi cũng cảm ơn bạn vì nó không bị kéo nữa. –

+0

Hah. Yea tôi cũng có chút ít điều này khi lần đầu tiên tôi bắt đầu làm việc với các bố cục có con đến và đi. – jdi

+7

Chỉ cần thêm vào một câu trả lời rất tốt: 'Q * Bố cục' không bao giờ là 'parent' của một widget vì cha của một widget phải là một widget và' Q * Layout' không xuất phát từ 'QWidget'. Họ chỉ hoạt động như một đại lý chuyển giao cho cha mẹ. Ngay cả khi bạn xóa tiện ích con khỏi bố cục, tiện ích vùng chứa vẫn giữ nguyên làm cha mẹ và nút của bạn vẫn ở đó. – Avaris

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