• 9341阅读
  • 6回复

[提问]QSplitter 的问题 [复制链接]

上一主题 下一主题
离线heyzol
 

只看楼主 倒序阅读 楼主  发表于: 2013-02-05
问题,窗体显示正常,点击退出后出现错误


窗体如下图


代码如下:

调试状态下运行,调试器提示如下:



  1. #include <QApplication>
  2. #include <QFont>
  3. #include <QPushButton>
  4. #include <QSplitter>
  5. #include <QTextEdit>
  6. #include <QTableWidget>
  7. #include <QTreeWidget>
  8. #include <QSettings>
  9. int main(int argc, char* argv[])
  10. {
  11.     QApplication app(argc, argv);
  12.     QTextEdit *editor1 = new QTextEdit;
  13.     QTableWidget *table = new QTableWidget;
  14.     QTreeWidget *tree = new QTreeWidget;
  15.     QSplitter vSplitter(Qt::Vertical);
  16.     vSplitter.addWidget(table);
  17.     vSplitter.addWidget(editor1);
  18.     QSplitter hSplitter(Qt::Horizontal);
  19.     hSplitter.addWidget(tree);
  20.     hSplitter.addWidget(&vSplitter);
  21.     hSplitter.show();
  22.     return app.exec();
  23. }





离线unizii

只看该作者 1楼 发表于: 2013-02-05
空指针问题,一般要继承一个类,在折构函数中销毁ui
离线realfan

只看该作者 2楼 发表于: 2013-02-05
从你代码可见,QTextEdit等控件是建立在堆上的,而app 是建立在栈上的。这些控件生命期长于app的生命期。
而Qt中,所有的 QPaintDevice 必须要在有QApplication实例的情况下创建和使用。QTextEdit等控件是属于QPaintDevice,它们在app生命期结束后,还存在,自然会出错。
离线zaq2010

只看该作者 3楼 发表于: 2013-02-05
回 楼主(heyzol) 的帖子
NEW的窗口部件在关闭的时候没有销毁
应该这样
  1. #include <QApplication>
  2. #include <QFont>
  3. #include <QPushButton>
  4. #include <QSplitter>
  5. #include <QTextEdit>
  6. #include <QTableWidget>
  7. #include <QTreeWidget>
  8. #include <QSettings>
  9. int main(int argc, char* argv[])
  10. {
  11.     QApplication app(argc, argv);
  12.     QSplitter hSplitter(Qt::Horizontal);
  13.     QTextEdit *editor1 = new QTextEdit(&hSplitter);
  14.     QTableWidget *table = new QTableWidget(&hSplitter);
  15.     QTreeWidget *tree = new QTreeWidget(&hSplitter);
  16.     QSplitter vSplitter(Qt::Vertical);
  17.     vSplitter.addWidget(table);
  18.     vSplitter.addWidget(editor1);
  19.     hSplitter.addWidget(tree);
  20.     hSplitter.addWidget(&vSplitter);
  21.     hSplitter.show();
  22.     return app.exec();
  23. }





离线realfan

只看该作者 4楼 发表于: 2013-02-06
楼上正解!
离线aresa
只看该作者 5楼 发表于: 2013-09-06
我认为楼上的解答都是错误的,没有弄清楚出错的根本原因。

楼主的程序会出错是因为没有理解QT控件之间的ownership关系。可以参考: http://qt-project.org/doc/qt-4.8/objecttrees.html

对于QSplitter::addWidget方法,添加进去的widget会自动成为QSplitter的child,而无需额外指定。
当一个Object被销毁时会delete其所有Children。这就是关键所在。
仔细查看QObject::~QObject的代码注释,其中明确说到:
“If any of these objects  are on the stack or global, sooner or later your program will crash.”
楼主的程序正是因为忽略了这一点而导致程序退出时crash,这是意料之中的。

回头看看你的程序,hSplitter在栈中要先于你的vSplitter被析构,而vSplitter也位于栈中并且是hSplitter的Child。
所以delete一个栈对象肯定会出错。

3楼的代码之所以能运行时因为他碰巧更改了hSplitter和vSplitter在栈中的顺序。所以vSplitter先于hSplitter被delete掉了,
而vSplitter会通知其parent自己已被析构,所有之后hSplitter析构时就不会再去delete它了。
离线jdwx

只看该作者 6楼 发表于: 2013-09-06
引用第5楼aresa于2013-09-06 14:16发表的  :
我认为楼上的解答都是错误的,没有弄清楚出错的根本原因。
楼主的程序会出错是因为没有理解QT控件之间的ownership关系。可以参考: http://qt-project.org/doc/qt-4.8/objecttrees.html
对于QSplitter::addWidget方法,添加进去的widget会自动成为QSplitter的child,而无需额外指定。
.......


正解,就是因为 QSplitter vSplitter(Qt::Vertical);在栈上。
Qt的内存管理机制,不会知道在栈上,关闭的时候回去delete所以出错,改为new。
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
快速回复
限100 字节
 
上一个 下一个