如何正确删除作为中心窗口小部件的QGraphicsView对象?

时间:2016-12-13 16:17:10

标签: c++ qt qwebkit

有以下代码。它创建了QGraphicsView对象,设置了一个场景,然后创建了一个添加到场景中的QGraphicsWebView对象:

QGraphicsWebView* graphicsWebView;
QGraphicsScene* graphicsScene;
QGraphicsView* graphicsView;
QMainWindow* mainWindow;

class Deleter : public QObject
{
    Q_OBJECT
public slots:
    void deleteWebView()
    {
        mainWindow->hide();
        mainWindow->centralWidget()->setParent(0);
        mainWindow->setCentralWidget(new QWidget());
        delete graphicsView; // <-- crashes about 2 seconds after that
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    mainWindow = new QMainWindow;
    graphicsView = new QGraphicsView;
    graphicsScene = new QGraphicsScene(graphicsView);
    graphicsView->setScene(graphicsScene);
    graphicsWebView = new QGraphicsWebView;
    graphicsWebView->setUrl(QUrl("http://www.google.com"));
    graphicsView->scene()->addItem(graphicsWebView);
    graphicsView->setViewport(new QGLWidget());
    graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    mainWindow->setAttribute(Qt::WA_TranslucentBackground);
    mainWindow->setCentralWidget(graphicsView);
    mainWindow->show();
    Deleter d;
    QTimer::singleShot(10000, &d, SLOT(deleteWebView()));
    return app.exec();
}

#include "main.moc"

10秒后,调用了一个试图删除QGraphicsView对象的插槽。问题是,当我尝试删除graphicsView时,程序在大约2秒钟后崩溃。回溯是垃圾。理论上QGraphicsView对象应该删除它的子节点,子节点是QGraphicsScene对象。场景应该删除它的子节点,即QGraphicsWebView对象。

如何正确删除QGraphicsView对象而不会导致进程崩溃?

这是Qt 4.8

2 个答案:

答案 0 :(得分:0)

我不明白为什么它没有正确清理,但我不会让graphicsView成为场景的父级。而不是给场景一个父级,只需在视图后的deleteWebView插槽中删除它。

答案 1 :(得分:0)

我无法重现。以下工作在OS X上的Qt 4.8.7上一致且没有崩溃:

#include <QtGui>
#include <QGraphicsWebView>
#include <QGLWidget>

class Window : public QMainWindow {
   Q_OBJECT
   QWidget central;
   QVBoxLayout layout{&central};
   QPointer<QGraphicsView> view;
   QPushButton button{"Toggle View"};
   Q_SLOT void toggle() {
      if (!view) {
         view = new QGraphicsView;
         auto scene = new QGraphicsScene(view);
         auto webView = new QGraphicsWebView;
         webView->setUrl(QUrl("http://www.google.com"));
         scene->addItem(webView);
         view->setScene(scene);
         view->setViewport(new QGLWidget);
         view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
         layout.addWidget(view);
      } else {
         delete view;
         view = nullptr;
      }
   }
public:
   Window() {
      layout.addWidget(&button);
      layout.addStretch(1);
      setAttribute(Qt::WA_TranslucentBackground);
      setCentralWidget(&central);
      connect(&button, SIGNAL(clicked(bool)), SLOT(toggle()));
   }
};

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   Window w;
   w.show();
   return app.exec();
}

#include "main.moc"