2012-12-11 16 views
6

Jaki jest "poprawny" lub idiomatyczny sposób czyszczenia/usuwania widgetów podczas korzystania z PyQt4?Właściwy sposób czyszczenia widgetów w pyqt

Rozważmy następujący kod:

choices = ['a', 'b', 'c'] 
checkboxes = [] 
layout = QtGui.QVBoxLayout() 

dialog = MyDialog() 

for c in choices: 
    checkboxes.append(QtGui.QCheckBox(c) 
    layout.addWidget(chkbox) 

dialog.setLayout(layout) 

for c in checkboxes: 
    c.setParent(None) 
    c.deleteLater() 
    c = None 

Powyższy kod wykorzystuje setParent(), deleteLater() i ustawienie przedmiotu do None. Czy wszystkie te są niezbędne?

Innym możliwym scenariuszem jest to, że mam okno dialogowe z wieloma widżetami i chcę usunąć te widżety i dodać nowe. Nie chcę "przeciekać" starych widżetów, ale nie jestem pewien, jaki byłby właściwy sposób na zrobienie czegoś takiego.

Wydaje mi się, że deleteLater() może nigdy nie być potrzebne. Czy po prostu zmniejsza licznik referencji? Jeśli tak, czy ustawienie zmiennej na None nie byłoby tym samym?

Odpowiedz

15

Pierwszą rzeczą, o której należy pamiętać, to używanie relacji rodzic/dziecko dla widżetów. Gdy to zrobisz, będą one własnością Qt i automatycznie usuwają wszystkie dzieci, gdy rodzic zostanie usunięty.

dialog = MyDialog() 

for c in choices: 
    checkboxes.append(QtGui.QCheckBox(c, parent=dialog)) 
    layout.addWidget(chkbox) 

W tej sytuacji wszystkie pola wyboru zostaną poprawnie wyczyszczone po usunięciu okna dialogowego. Zajmuje się jedną częścią twojego pytania. Zdaję sobie sprawę, że niejawnie masz ustawiony rodzic, gdy dodasz je do układu. Ale nie należy usuwać tego rodzica przed usunięciem. Jest to relacja nadrzędna, która umożliwia automatyczne usunięcie dziecka. Nie liczy się liczba referencyjna. Aspektem referencyjnym byłaby rzecz po stronie Pythona, w której zostanie zebrane śmieci, gdy nie będzie już żadnych odniesień do niego.

deleteLater jest bardzo ważny, do użycia, gdy chcesz, aby usunięcie nastąpiło, gdy kontrola wraca do zdarzenia. Jest to również sposób na bezpieczne usuwanie widżetów gdy usuwasz niektóre z układu i dodawanie nowych:

# clear a layout and delete all widgets 
# aLayout is some QLayout for instance 
while aLayout.count(): 
    item = aLayout.takeAt(0) 
    item.widget().deleteLater() 

Te wzory będą faktycznie usunięte raz ta metoda została zakończona. deleteLater jest również przydatny do usuwania widżetu, w którym aktualnie ma miejsce slot lub zdarzenie. Takich jak QPushButton, które mogą się same usuwać po kliknięciu.

Nie ma również dużej potrzeby ustawiania wartości c = None. Po usunięciu elementu nadrzędnego, który powoduje usunięcie wszystkich jego elementów podrzędnych, rekurencyjnie, odwołania Pythona do tego obiektu będą nieprawidłowe. Więc wszystko, co musisz zrobić, to po prostu nie używać ich więcej. Jeśli znajdują się na liście, wyczyść listę. Uzyskanie dostępu do nich podniosłoby wartość RuntimeError: wrapped C/C++ object of %S has been deleted, co oznacza, że ​​zostaną usunięte.

+0

Czy konieczne jest użycie argumentu "rodzic" podczas tworzenia wszystkich obiektów, które zostaną dodane do układu? Zdaję sobie sprawę, że jest to prawdopodobnie trochę bardziej wyraźne, ale czy jest to wymagane? –

+0

Naprawdę nie. Jeśli dodasz je bezpośrednio do układu, układ sprawi, że będą one dziećmi właściciela układu. – jdi

+0

Bardzo późno na imprezę, ale pomyślałem, że mogę to dodać - chociaż nie jest konieczne używanie argumentu "rodzic" - to chyba dobry pomysł, ponieważ ogranicza on trochę strukturę twojego kodu i ułatwia innym aby zobaczyć, jaka jest zamierzona hierarchia powstrzymywania. – Emmet

Powiązane problemy