[英]Deleting Pointer to widget Qt C++
我是Qt的新手,我對如何刪除小部件非常困惑。 我正在閱讀視頻,我想在讀取視頻幀時顯示QProgressbar,然后在加載視頻時刪除此QProgressbar。
我用兩種不同的方式做到了:
使用指針
QWidget* wd = new QWidget(); QProgressBar* pB = new QProgressBar(wd); QLabel* label = new QLabel(wd); //setting geometry and updating the label and progressbar wd->deleteLater(); wd->hide();
這段代碼寫在一個類中,我假設當調用這個類的析構函數時,小部件將被刪除所有的子節點,但是沒有發生,每次我再次運行這個函數時,創建一個新的小部件而不隱藏或者刪除前一個(注意:我試圖從小部件中刪除標簽和進度條,假設它們將從小部件內部消失,但這不會發生“刪除(pB);”)
使用對象
QWidget wd; QProgressBar pB(&wd); QLabel label(wd); //setting geometry and updating the label and progressbar wd.deleteLater(); wd.hide();
當我運行相同的代碼但使用對象而不是指針時,它運行完全如我所希望的那樣,每次運行該函數時,舊的小部件都會被銷毀並創建一個新的小部件。
注意: - 當我關閉主窗口時,如果指針,小部件wd仍然存在,程序不會終止,直到我手動關閉它們 - 如果是對象,當我關閉主窗口時,一切都關閉,程序正確終止。
我需要有人解釋我為什么會發生這種情況以及如果我有一個指向小部件的指針向量來刪除該向量內的所有指針而沒有任何內存泄漏
在典型的C ++中,規則是“為每個new
寫一個delete
”。 一個更高級的規則是“可能不會寫new
或delete
並以RIAA模式埋葬”。 Qt在這方面改變了規則,因為它引入了自己的內存管理范例。 它基於父/子關系。 new
ed的QWidget
可以給出parentWidget()
。 當parentWidget()
被銷毀時,它的所有子parentWidget()
都將被銷毀。 因此,在Qt中,通常的做法是使用new
在堆棧上分配對象,給它們一個父級,並且永遠不要自己delete
內存。 QLayout
規則變得更加復雜,有時候Qt對象會占用小部件,有時則不會。
在您的情況下,您可能不需要deleteLater
調用。 這會向Qt的內部事件循環發布消息。 消息說:“當你有機會時刪除我!” 如果你想在班級管理wd
只要給它的父this
。 刪除類后,將刪除整個父/子樹。
這一切都非常簡單。 QObject
派生類與任何其他C ++類一樣,但有一個例外:如果QObject
有子QObject
,它將刪除其析構函數中的子節點。 請記住, QWidget
是一個QObject. If you have an instance allocated using
QObject. If you have an instance allocated using
new` QObject. If you have an instance allocated using
,你必須刪除它,或者確保某些東西(一個智能指針!)。
當然,嘗試delete
未動態分配的內容是一個錯誤,因此:
如果沒有動態分配一個QObject
, 不 deleteLater
或delete
它。
如果不動態分配QObject
的子QObject
,請確保在對象被破壞之前它們已經消失。
此外, 不要隱藏您即將破壞的小部件 。 沒有用。
要自己管理窗口小部件生命周期,您應該使用智能指針:
class MyClass {
QScopedPointer<QWidget> m_widget;
public:
MyClass() :
widget{new QWidget};
{
auto wd = m_widget->data();
auto pb = new QProgressBar{wd};
auto label = new QLabel{wd};
}
};
當你破壞MyClass
,范圍指針的析構函數將刪除小部件實例,其QObject::~QObject
析構函數將刪除其子級。
當然,這些都不是必需的:您應該只是將對象創建為類的直接成員:
class MyClass {
// The order of declaration has meaning! Parents must precede children.
QWidget m_widget;
QProgressBar m_bar{&m_widget};
QLabel m_label{&m_widget};
public:
MyClass() {}
};
通常,您將使用子窗口小部件的布局:
class MyClass {
QWidget m_widget;
QVBoxLayout m_layout{&m_widget};
QProgressBar m_bar;
QLabel m_label;
public:
MyClass() {
m_layout.addWidget(&m_bar);
m_layout.addWidget(&m_label);
}
};
當您向布局添加窗口小部件時,它會將它們重新設置為已設置布局的窗口小部件。
編譯器生成的析構函數如下所示。 你不能編寫這樣的代碼,因為編譯器生成的代碼會雙重破壞已經被破壞的對象,但讓我們假裝你可以。
MyClass::~MyClass() {
m_label.~QLabel();
m_bar.~QProgressBar();
m_layout.~QVBoxLayout();
// At this point m_widget has no children and its `~QObject()` destructor
// won't perform any child deletions.
m_widget.~QWidget();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.