转自:http://blog.csdn.net/qq575787460/article/details/7824633
一、new与delete
在C++学习中,new与delete必须成对使用,防止内存泄漏,可是在学习Qt时,我发现很多new,而却几乎找不到delete。在网上搜索得知:Qt完善了C++的内存管理机制,“如果指针对象有父对象,那么父对象在被释放时,会自动释放子对象”。所以我在练习时,创建的控件都传递了this指针,作为其父对象。
但是,当我在练习布局管理器的时候,却出了问题。
二、传递了父对象指针的控件在布局管理器中不能正常显示
- #include <QApplication>
- #include <QTableWidget>
- #include <QStringList>
- #include <QPushButton>
- #include <QVBoxLayout>
- #include <QHBoxLayout>
- #include <QWidget>
- int main(int argc,char *argv[])
- {
- QApplication app(argc,argv);
- QWidget *mainWindow=new QWidget;
- mainWindow->setAttribute(Qt::WA_DeleteOnClose);
- QTableWidget *tabStudent=new QTableWidget(3,3,mainWindow);
- tabStudent->setHorizontalHeaderLabels(QStringList()<<"name"<<"sex"<<"age");
- QPushButton *btnInsert=new QPushButton("insert",mainWindow);
- QPushButton *btnDelete=new QPushButton("delete",mainWindow);
- QHBoxLayout *bottomLayout=new QHBoxLayout(mainWindow);
- bottomLayout->addWidget(btnInsert);
- bottomLayout->addWidget(btnDelete);
- QVBoxLayout *mainLayout=new QVBoxLayout(mainWindow);
- mainLayout->addWidget(tabStudent);
- mainLayout->addLayout(bottomLayout);
- mainWindow->setLayout(mainLayout);
- mainWindow->show();
- return app.exec();
- }
结果显示,错乱:
经过尝试,不给bottomLayout传递父对象指针时,可以正常显示
- #include <QApplication>
- #include <QTableWidget>
- #include <QStringList>
- #include <QPushButton>
- #include <QVBoxLayout>
- #include <QHBoxLayout>
- #include <QWidget>
- int main(int argc,char *argv[])
- {
- QApplication app(argc,argv);
- QWidget *mainWindow=new QWidget;
- mainWindow->setAttribute(Qt::WA_DeleteOnClose);
- QTableWidget *tabStudent=new QTableWidget(3,3,mainWindow);
- tabStudent->setHorizontalHeaderLabels(QStringList()<<"name"<<"sex"<<"age");
- QPushButton *btnInsert=new QPushButton("insert",mainWindow);
- QPushButton *btnDelete=new QPushButton("delete",mainWindow);
- QHBoxLayout *bottomLayout=new QHBoxLayout();//修改此处,不传递父对象指针
- bottomLayout->addWidget(btnInsert);
- bottomLayout->addWidget(btnDelete);
- QVBoxLayout *mainLayout=new QVBoxLayout(mainWindow);
- mainLayout->addWidget(tabStudent);
- mainLayout->addLayout(bottomLayout);
- mainWindow->setLayout(mainLayout);
- mainWindow->show();
- return app.exec();
- }
三、布局管理器对内嵌布局管理器和窗体父对象的影响
经过查找帮助文档,终于一探究竟。
首先看一下帮助文档对void QWidget::setLayout ( QLayout * layout )这个函数的说明:
Sets the layout manager for this widget to layout.
If there already is a layout manager installed on this widget, QWidget won't let you install another. You must first delete the existing layout manager (returned by layout()) before you can call setLayout() with the new layout.
If layout is the layout manger on a different widget, setLayout() will reparent the layout and make it the layout manager for this widget.
中文意思大概是:设置窗体的布局管理器为layout。如果窗体已经安装了一个布局管理器,窗体不会再安装另一个布局管理器。
在调用setLayout()安装新的布局管理器之前,你必须首先删除窗体上已经安装的布局管理器。
如果是另一个窗体上安装的布局管理器,setLayout() 会重置这个布局管理器的父对象(为调用setLayout()的窗体)。
由此可以看出,当bottomLayout和mainLayout都指定父对象时,后创建的布局管理器并没有被安装在窗体上,所以不给bottomLayout传递父对象指针时,mainLayout可以被正常安装。
为了验证是否真的不能再次安装,布局管理。做下面的实验:
小提示:
When you use a layout, you do not need to pass a parent when constructing the child widgets. The layout will automatically reparent the widgets (using QWidget::setParent()) so that they are children of the widget on which the layout is installed.
Note: Widgets in a layout are children of the widget on which the layout is installed, not of the layout itself. Widgets can only have other widgets as parent, not layouts.
You can nest layouts using addLayout() on a layout; the inner layout then becomes a child of the layout it is inserted into.
我在有道翻译的帮助下,终于把这段话翻译了下来:当你使用布局管理器时,你不需要为子窗体传递父对象指针,布局管理器会自动重置子窗体父亲为安装了这个布局管理器的窗体。在布局管理器内的窗体的父亲是安装了这个布局管理器的窗体,而不是这个布局管理器。窗体的父亲只能是窗体。当使用addlayout的时候,内嵌的layout会成为调用addlayout的那个管理器的子对象。
四、总结
学习Qt将近20天,终于写篇成长日记。一定要勤于动手调试。
- #include <QApplication>
- #include <QTableWidget>
- #include <QStringList>
- #include <QPushButton>
- #include <QVBoxLayout>
- #include <QHBoxLayout>
- #include <QWidget>
- int main(int argc,char *argv[])
- {
- QApplication app(argc,argv);
- QWidget *mainWindow=new QWidget;
- mainWindow->setAttribute(Qt::WA_DeleteOnClose);
- QTableWidget *tabStudent=new QTableWidget(3,3);//tabStudent没有父亲
- tabStudent->setHorizontalHeaderLabels(QStringList()<<"name"<<"sex"<<"age");
- QPushButton *btnInsert=new QPushButton("insert");//btnInsert没有父亲
- QPushButton *btnDelete=new QPushButton("delete");//btnDelete没有父亲
- QHBoxLayout *bottomLayout=new QHBoxLayout;//bottomLayout没有父亲
- bottomLayout->addWidget(btnInsert);//btnInsert没有父亲
- bottomLayout->addWidget(btnDelete);//btnDelete没有父亲
- QVBoxLayout *mainLayout=new QVBoxLayout;//mainLayout没有父亲
- mainLayout->addWidget(tabStudent);//tabStudent没有父亲
- mainLayout->addLayout(bottomLayout);//设置bottomLayout的父亲为mainLayout tabStudent,btnInsert,btnDelete没有父亲
- mainWindow->setLayout(mainLayout);
- //设置mainLayout的父亲为mainWindow tabStudent,btnInsert,btnDelete的父亲为mainWidget
- mainWindow->show();
- return app.exec();
- }
- /*
- 可以分析出:mainWindow的直接子对象为;mainLayout,tabStudent,btnInsert,btnDelete
- mainLayout的直接子对象为bottonLayout
- 所以mainWindow释放的时候,会析构mainLayout,tabStudent,btnInsert,btnDelete
- mainLayout又会析构bottomLayout
- */