2012-12-11 3 views
6

Quelle est la manière «correcte» ou idiomatique de nettoyer/supprimer des widgets lors de l'utilisation de PyQt4?Une bonne façon de nettoyer les widgets en pyqt

Consultez le code suivant:

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 

Le code ci-dessus utilise setParent(), deleteLater() et réglage de l'objet à None. Sont-ils tous nécessaires?

Un autre scénario possible est que j'ai un dialogue avec un tas de widgets et que je veux supprimer ces widgets et en ajouter de nouveaux. Je ne veux pas 'laisser échapper' les vieux widgets, mais je ne suis pas sûr de la façon correcte de faire quelque chose comme ça. Il me semble que deleteLater() pourrait ne jamais être nécessaire. Est-ce que cela décrémente simplement le nombre de références? Si oui, est-ce que le fait de mettre la variable à None ne ferait pas la même chose?

Répondre

15

La première chose à faire est d'utiliser les relations parent/enfant pour vos widgets. Lorsque vous faites cela, ils seront la propriété de Qt et nettoiera automatiquement tous les enfants lorsque le parent est supprimé.

dialog = MyDialog() 

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

Dans cette situation, toutes les cases à cocher seront correctement nettoyées lorsque vous supprimez la boîte de dialogue. Cela gère une partie de votre question. Je me rends compte que vous avez implicitement le parent défini lorsque vous les ajoutez à la mise en page. Mais vous ne devriez pas effacer ce parent avant de le supprimer. Il est la relation parent qui permet à l'enfant d'être automatiquement supprimé. Pas un compte de référence. L'aspect de référence serait une chose python-side où il sera récupéré garbage quand il n'y a plus de références à celui-ci.

deleteLater est très important, à utiliser lorsque vous souhaitez que la suppression se produise lorsque le contrôle revient à l'eventloop. Il est également le moyen sûr de supprimer des widgets lorsque vous supprimer certains d'une mise en page et en ajoutant de nouvelles:

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

Ces widgets seront effectivement supprimés une fois que cette méthode est terminée. deleteLater est également utile pour supprimer le widget sous lequel l'emplacement ou l'événement se produit actuellement. Comme un QPushButton qui peut se supprimer sur un clic.

Il n'y a pas non plus besoin de régler c = None. Une fois qu'un parent est supprimé, et que cela déclenche la suppression de tous ses enfants, récursivement, vos références python à cet objet seront invalides. Donc tout ce que vous devez faire est de ne plus les utiliser. S'ils sont dans une liste, effacez la liste. Leur accès augmenterait le RuntimeError: wrapped C/C++ object of %S has been deleted ce qui signifie qu'ils sont supprimés.

+0

Est-il nécessaire d'utiliser l'argument 'parent' lors de la création de tous les objets qui seront ajoutés à une mise en page? Je réalise que c'est probablement un peu plus explicite, mais est-ce nécessaire? –

+0

Non, pas vraiment. Si vous les ajoutez directement à la mise en page, la disposition les rendra enfants du propriétaire de la mise en page. – jdi

+0

Très en retard à la fête, mais je pensais que j'ajouterais - bien que ce ne soit pas _necessary_ d'utiliser l'argument 'parent' - c'est probablement une bonne idée, car cela contraint un peu la structure de votre code pour voir quelle est la hiérarchie de confinement prévue. – Emmet

Questions connexes