Как правильно удалить объект QGraphicsView, который был центральным виджетом?

Есть следующий код. Он создает объект 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


person Ciomco    schedule 13.12.2016    source источник
comment
Нет причин делать лишнюю акробатику вокруг центрального виджета: просто удалите виджет, когда он вам больше не нужен.   -  person Kuba hasn't forgotten Monica    schedule 14.12.2016


Ответы (2)


Я не понимаю, почему он не очищается должным образом, но я бы не стал делать GraphicsView родителем вашей сцены. Вместо того, чтобы давать сцене родителя, просто удалите его в своем слоте deleteWebView после представления.

person goug    schedule 13.12.2016

Я не могу воспроизвести. Следующее работает стабильно и без сбоев в Qt 4.8.7 на OS X:

#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"
person Kuba hasn't forgotten Monica    schedule 13.12.2016