一文詳解Qt中的對象樹機制
Qt提供了對象樹機制,能夠自動、有效的組織和管理繼承自QObject的Qt對象。
每個繼承自QObject類的對象通過它的對象鏈表(QObjectList)來管理子類對象,當用戶創(chuàng)建一個子對象時,其對象鏈表相應更新子類對象信息,對象鏈表可通過children()獲取。
當父對象析構的時候,其對象鏈表中的所有(子)對象也會被析構,父對象會自動將其從父對象列表中刪除。Qt 保證沒有對象會被 delete 兩次。開發(fā)中手動回收資源時建議使用deleteLater代替delete,因deleteLater多次是安全的,而delete多次是不安全的。
示例
新建QWidget項目。添加四個類,分別繼承QLable、QPushButton、QRadioButton、QGridLayout
class MyLabel : public QLabel; class MyLayout : public QGridLayout; class MyPushButton : public QPushButton; class MyRadioButton : public QRadioButton;
每個子類聲明構造和析構函數,函數實現中僅使用qDebug( )輸出標識句
//MyLabel類
MyLabel::MyLabel(QWidget *parent):QLabel(parent)
{
qDebug()<<"MyLabel構造"<<this;
}
MyLabel::~MyLabel()
{
qDebug()<<"MyLabel析構"<<this;
}
//MyLayout類
MyLayout::MyLayout(QWidget *parent):QGridLayout(parent)
{
qDebug()<<"MyLayout構造"<<this;
}
MyLayout::~MyLayout()
{
qDebug()<<"MyLayout析構"<<this;
}
//MyPushButton類
MyPushButton::MyPushButton(QWidget *parent):QPushButton(parent)
{
qDebug()<<"MyPushButton構造"<<this;
}
MyPushButton::~MyPushButton()
{
qDebug()<<"MyPushButton析構"<<this;
}
//MyRadioButton類
MyRadioButton::MyRadioButton(QWidget *parent):QRadioButton(parent)
{
qDebug()<<"MyRadioButton構造"<<this;
}
MyRadioButton::~MyRadioButton()
{
qDebug()<<"MyRadioButton析構"<<this;
}在main函數中,初始化控件和布局管理器,將當前窗體設為控件和布局管理器的父窗體;將控件添加到布局管理器中
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
//當前窗體設為父窗體
MyLabel *myLabel =new MyLabel(&w);
MyPushButton*myBtn=new MyPushButton(&w);
MyRadioButton*myRbtn=new MyRadioButton(&w);
MyLayout*myLayout=new MyLayout(&w);
//設置文本
myLabel->setText("子標簽");
myBtn->setText("子按鈕");
myRbtn->setText("子單選");
//控件添加到布局管理器中
myLayout->addWidget(myLabel,0,0);
myLayout->addWidget(myBtn,1,0);
myLayout->addWidget(myRbtn,2,0);
return a.exec();
}運行結果:


我們可以看到:在初始化時,當前窗體會先執(zhí)行構造,隨后是其子類執(zhí)行構造;當窗體關閉時,當前窗體會先執(zhí)行析構,隨后是其子類執(zhí)行析構,也就是說程序會自動、有效的組織和管理繼承自QObject的Qt對象。 只要父類是QObject下的派生類,當父類被銷毀或者創(chuàng)建時,其子類也會跟著創(chuàng)建和銷毀。
我們可以使用.children( )函數查看一個類的派生類。這里我們查看當前窗體的派生類。
const QObjectList listW=w.children();
qDebug()<<"w.children()";
foreach (QObject* obj, listW) {
qDebug()<<obj;
}
運行結果:

從運行結果我們可以看到: 當我們對控件和布局管理器初始化時,已經將當前窗體設為其父窗體。這些控件和布局管理器也就順應成章成為當前窗體的子類。
我們繼續(xù)對標簽控件派生子類
//創(chuàng)建一個sun布局管理器,將標簽控件設為其父窗體
MyLayout*sunLayout=new MyLayout(myLabel);
//創(chuàng)建三個按鈕控件,這里并未指明其父窗體
MyPushButton*sunBtn1=new MyPushButton;
MyPushButton*sunBtn2=new MyPushButton;
MyPushButton*sunBtn3=new MyPushButton;
//設置文本
sunBtn1->setText("孫按鈕1");
sunBtn2->setText("孫按鈕2");
sunBtn3->setText("孫按鈕3");
//將按鈕添加到布局管理器中
sunLayout->addWidget(sunBtn1);
sunLayout->addWidget(sunBtn2);
sunLayout->addWidget(sunBtn3);
//按鈕初始時未設定父類,只是將其放入sun布局管理器中。
//sun布局管理器的父窗體設定為myLabel,當myLabel指定其布局管理器為孫布局管理器時,按鈕會重新將myLabel設定為其父窗體
myLabel->setLayout(sunLayout);


繼續(xù)使用.children( )查看標簽類的派生類
//查看w子類
const QObjectList listW=w.children();
qDebug()<<"w.children()";
foreach (QObject* obj, listW) {
qDebug()<<obj;
}
//查看myLabel子類
const QObjectList listLabel=myLabel->children();
qDebug()<<"myLabel.children()";
foreach (QObject* obj, listLabel) {
qDebug()<<obj;
}
執(zhí)行結果:

以上就是一文詳解Qt中的對象樹機制的詳細內容,更多關于Qt對象樹機制的資料請關注腳本之家其它相關文章!

