0
QObject::deleteLater()
delete obj;析構對象
1
QWidget::setVisible(bool)
使得Widget可見或不可見
2
QWidget::setHidden(bool)
1號的馬甲
3
QWidget::show()
1號的馬甲
4
QWidget::hide()
1號的馬甲
5
QWidget::close()
視情況確定是否調用4號0號
6
QDialog::done(int)
始終會調用4號,視情況調用0號
7
QDialog::accept()
6號的馬甲
8
QDialog::reject()
6號的馬甲
寫在前面
我們知道,
分配到heap中的對象(通過 new),當對其delete,才會被析構。
分配在stack中的對象,當其離開作用域是被析構
在 Qt 中,一般建議你使用 new 的方式創建對象。或者,你可以看看 從 Qt 的 delete 說開來
注意:
本文接下來的討論,都是假定你用的 new 創建的對象。
QObject
從Qt類的祖宗開始吧。因為QObject不涉及界面啊,成員中只涉及析構問題。在從 Qt 的 delete 說開來 一文中,我們知道,
obj->deleteLater();
最后調用的就是:
delete obj;
很簡單哈。所以,這個函數的談論(略)
另外:對象析構時會發射 destroyed 信號。注意,是對象析構時,這是句廢話,但要記住。
QWidget
setVisible
呵呵,show()、hide()、setVisible()、setHidden() 這4個函數讓人看得眼花繚亂。怎么辦?
看看代碼吧:
virtual void setVisible(bool visible);
inline void setHidden(bool hidden) { setVisible(!hidden); }
inline void show() { setVisible(true); }
inline void hide() { setVisible(false); }
代碼很清楚:這四個東西之中,只有 setVisible 是獨立的,其他三個都是它的馬甲!
setVisible 的作用是什么呢?顧名思義,使得一個Widget可見或不可見。
要點:不可見,是Widget不在界面上顯示,但不代表對象被析構!
close
這個函數,Manual中給的其實很詳細的,很透徹。但一開始想弄明白還真是不容易。
首先,我們直接調用close時(或者點擊關閉按鈕調用),它會生成 QCloseEvent 事件:(我們可以選擇接受或阻止它,如果我們阻止事件,close將直接返回,什么都不做)
看點源碼:
bool QWidgetPrivate::close_helper(CloseMode mode)
{
...
QCloseEvent e;
if (mode == CloseWithSpontaneousEvent)
QApplication::sendSpontaneousEvent(q, &e);
else
QApplication::sendEvent(q, &e);
if (!that.isNull() && !e.isAccepted()) {
data.is_closing = 0;
return false;
}
...
}
其次:如果我們接受了事件(默認),她就直接調用我們前面提到的朋友。(從界面上干掉)
q->hide();
再次:如果我們為它設置過標記位(關閉時刪除它):又看到老朋友不是?(從內存中干掉)
if (q->testAttribute(Qt::WA_DeleteOnClose)) {
q->setAttribute(Qt::WA_DeleteOnClose, false);
q->deleteLater();
}
題外:close 還是其他代碼,但與本主題無關,不再涉及。
QDialog
QDialog 和 QWidget 相比,多了 done、reject 和 accept 3個相關函數:
先看看兩個馬甲:
void QDialog::accept()
{
done(Accepted);
}
void QDialog::reject()
{
done(Rejected);
}
done
done 做的事情和close比較類似:因為它調用了close所調用的 close_helper 函數。只不過不同於close函數,它始終會先讓Widget不可見。然后close操作,最后根據參數發射信號
void QDialog::done(int r)
{
Q_D(QDialog);
hide();
setResult(r);
d->close_helper(QWidgetPrivate::CloseNoEvent);
emit finished(r);
if (r == Accepted)
emit accepted();
else if (r == Rejected)
emit rejected();
}
注意:QDilaog可能包含事件循環,事件循環由QDialog::exec() 開始,QDialog::setVisible(false)將負責退出事件循環,這兒用的是其馬甲hide()。