2012-03-28 22 views
17

PySide uygulamasında bir düzenden Qt widget'ını kaldırmaya çalışıyorum.PySide: Bir widget öğesinin düzeninden kaldırılması

İşte en az bir örnek. İçinde 5 düğmeleri olan bir widget ve tıklandığında Orta şerit kendisini kaldırmak gerekiyordu:

What actually happens

düğmesi açıkça tıklanamayan ve geçerli:

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_() 

gerçekte neler oluyor şudur Düzen hesaplamaları için dikkate alınmaz, ancak görüntüsü yerinde kalır. İşte

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

Sadece üçüncü düğmeye silmek istiyorum, bu yüzden sadece aramak için daha sonra del btakeAt(2) arama ve:

Qt documentation göre, bir düzenden tüm nesneleri silme doğru yoldur Bu öğe üzerinde yıkıcı. Nesne için artık referans olmadığından emin olmak için, düğme nesnesi buttons listesinden .pop 'd'dir. Kodum, Qt belgelerinde bu tür davranışlara neden olandan nasıl farklıdır?

+5

Sadece gerçekten iyi oluşturulmuş bir sorudan dolayı sizi tebrik etmek istiyorum. Son zamanlarda o kadar çok şey görüyorum ki, sadece bağlamı olmayan birkaç cümle ya da okumamız beklenen büyük miktarda kod. Bu son derece özlü ve uygulanabilir kod örneği ile birlikte, belirtilen çok net bir soruna sahiptir. Resimleriniz ayrıca konuyu daha da netleştiriyor. Ve ne denediğini gösterirsin. Bravo! – jdi

cevap

28

Süper basit bir düzeltme:

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

Önce sen düzenden döndürülür gerçek düğmeye değil QWidgetItem ele emin olmak için, ve sonra yok etmek Qt söyleyecektir deleteLater() call bu yuvadan sonra widget sona erer ve kontrol, olay döngüsüne geri döner.

Başka bir örnek, sorunun neden oluştuğunu gösterir. Mizanpaj öğesini almanıza rağmen, temeldeki widget hala orijinal düzenler widget'ına ayrılmıştır.

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

Bu, nesnenin temizlenmesini hala belirsiz bıraktığı için tercih edilen yol değildir. Ancak, ebeveynin silinmesinin görsel ekrandan çıkmasına izin verdiğini gösterir. Yine de deleteLater() kullanın. Her şeyi düzgün bir şekilde temizler.

+0

Mükemmel, teşekkürler ~ Saçlarım da teşekkürler çünkü artık çekilmiyor. –

+0

Hah. Çocuklarımın gelip gittiği düzenlerle çalışmaya başladığımda, ben de bundan anladım. – jdi

+7

Sadece çok iyi bir cevaba eklemek için: 'Q * Layout 'bir widget'ın asla' parent''i değildir, çünkü bir widget'ın ana öğesi başka bir widget olmalıdır ve' Q * Layout' 'QWidget'den türetilmemiştir. Onlar sadece ebeveynlik için bir transfer ajanı olarak hareket ederler. Widget'ı bir düzenden kaldırsanız bile, kapsayıcı pencere öğesi hala ebeveyn olarak kalır ve düğmeniz hala oradadır. – Avaris