2012-12-11 54 views
6

使用PyQt4時,清理/刪除小部件的「正確」或習慣用法是什麼?在pyqt中清理小部件的正確方法

考慮下面的代碼:

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 

上面代碼使用setParent()deleteLater(),對象設置爲None。這些都是必要的嗎?

另一種可能的情況是我有一個對話框,其上有一些小部件,並希望刪除這些小部件並添加新的部件。我不想'泄漏'舊的窗口小部件,但我不確定做這種事情的正確方法是什麼。

在我看來,deleteLater()可能永遠不需要。它只是減少引用計數?如果是這樣,不會只是將變量設置爲None做同樣的事情?

回答

15

你應該記住的第一件事是爲你的小部件使用父/子關係。當你這樣做時,他們將由Qt所有,並且在父母被刪除時將自動清理所有孩子。

dialog = MyDialog() 

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

在這種情況下,當您刪除對話框時,所有複選框將被正確清理。這處理你的問題的一部分。我意識到,當你將它們添加到佈局時,你隱式地設置了父設置。但是,在刪除之前,您不應該清除該父母。它父母的關係,允許孩子被自動刪除。不是參考計數。參考方面將是一個python方面的事情,它會在沒有更多引用時收集垃圾。

deleteLater是非常重要的,當您希望當控件返回到事件回調時發生刪除時使用。這也是刪除當你從佈局移除一些動作並添加新的小部件的安全方法:

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

一旦該方法完成這些小工具實際上將被刪除。 deleteLater對於刪除插槽或事件當前正在發生的小部件也很有用。如QPushButton可以在點擊時自行刪除。

有沒有太多需要設置c = None。一旦父項被刪除,並且會以遞歸方式觸發刪除其所有子項,那麼對該對象的Python引用將無效。所以你只需要不再使用它們。如果他們在列表中,清除列表。訪問它們會提高RuntimeError: wrapped C/C++ object of %S has been deleted這意味着它們被刪除。

+0

創建所有將添加到佈局的對象時,是否需要使用'parent'參數?我意識到這可能更加明確一點,但它是否需要? –

+0

不,不是真的。如果您直接將它們添加到佈局,則佈局將使它們成爲佈局所有者的子項。 – jdi

+0

這次聚會很晚,但我想補充一點 - 雖然不需要使用「parent」參數 - 但這可能是一個好主意,因爲它會稍微限制代碼的結構,並且使其他人更容易看看預期的收容等級是什麼。 – Emmet