Error code after inheriting QGraphicsView
Hi everyone!
I have some problem with QGraphicsView. I want to create a program that will allow me to draw rectangles on loaded image. I have created my own GraphicsView class that inherits from QGraphicsView and I have overloaded QGraphicsView::mouseReleaseEvent to get the mouse position. I also added 'Widget' from Qt Creator to my form and replaced it with my class. It works fine until I close the window. After that I get an error code (-1073741819). Debugger shows segmentation fault in function QScopedPointer (no idea why). Probably I have to call some function, but I don't know which one and where. I will show you my code (only .cpp). Tell me if you need the header files.
I hope you understand what I mean:) Could you help me?
MainWindow class:
Code:
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow
::MainWindow(QWidget *parent
) : QWidget(parent
), ui
(new Ui
::MainWindow){
ui->setupUi(this);
ui->widget->setScene(&scene);
connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(close()));
connect(ui->loadButton, SIGNAL(clicked()), this, SLOT(loadImage()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::loadImage()
{
image.load(fileName);
scene.addPixmap(image);
ui->widget->loadImage(image);
ui->widget->show();
}
GraphicsView class:
Code:
#include "GraphicsView.h"
{
firstRect = true;
}
GraphicsView::~GraphicsView()
{
scene()->clear();
}
void GraphicsView
::loadImage(QPixmap item
) {
image = item;
}
void GraphicsView
::mouseReleaseEvent(QMouseEvent *event
) {
if(point1.isNull())
{
point1.setX(event->x());
point1.setY(event->y());
}
else
{
point2.setX(event->x());
point2.setY(event->y());
int width = point2.x() - point1.x();
int height = point2.y() - point1.y();
if(firstRect)
{
rect.setRect(point1.x(), point1.y(), width, height);
rect.
setPen(QPen(Qt
::red));
firstRect = false;
}
else
{
scene()->removeItem(&rect);
rect.setRect(point1.x(), point1.y(), width, height);
}
scene()->clear();
scene()->addPixmap(image);
scene()->addItem(&rect);
point1.setX(0);
point1.setY(0);
}
event->accept();
}
Platform: Windows 7
Qt: 4.7.0
Thanks in advance
Kuba
Re: Error code after inheriting QGraphicsView
Please provide a backtrace from the crash.
Re: Error code after inheriting QGraphicsView
Code:
0 QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> >::data qscopedpointer.h 135 0x00fc8bee
1 qGetPtrHelper<QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> > > qglobal.h 2328 0x00de5b5d
4 ~GraphicsView GraphicsView.cpp 10 0x00401f02
5 QObjectPrivate::deleteChildren qobject.cpp 1949 0x6a2120f8
6 ~
QWidget qwidget.
cpp 1589 0x008938e8
7 ~MainWindow MainWindow.cpp 16 0x004018be
8 qMain main.cpp 10 0x0040140d
9 WinMain@16 qtmain_win.cpp 131 0x00402892
10 main 0 0x004025b8
Re: Error code after inheriting QGraphicsView
Please show us how you created the view and scene objects.
Re: Error code after inheriting QGraphicsView
The scene object is a private member of MainWindow class (not pointer) and the view, just as I said, was replaced with the "widget" object in Qt Designer so I don't create it myself. I will provide the header files to be clear:
MainWindow.h:
Code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QWidget>
#include <QtGui>
namespace Ui
{
class MainWindow;
}
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
public slots:
void loadImage();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
GraphicsView.h
Code:
#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H
#include <QGraphicsView>
#include <QtGui>
{
Q_OBJECT
public:
explicit GraphicsView
(QWidget *parent
= 0);
~GraphicsView();
signals:
public slots:
private:
bool firstRect;
};
#endif // GRAPHICSVIEW_H
Now you have almost all my code (only main is left).
Re: Error code after inheriting QGraphicsView
Wild guess: Check if scene() returns a valid pointer in GraphicsView's destructor.
Re: Error code after inheriting QGraphicsView
I would suspect there is a parent-child relationship between some objects that causes double deletion of something but I can't see anything like that in the code.
Re: Error code after inheriting QGraphicsView
Code:
// qgraphicsscene.cpp
//...
// Recursive descent delete
for (int i = 0; i < d->indexedItems.size(); ++i) {
if (!item->parentItem())
delete item; //!< here
}
}
Maybe scene tries to delete your rect created on stack. Try to call removeItem() before clear() and see if it still crashes:
Code:
GraphicsView::~GraphicsView()
{
scene()->removeItem(&rect);
scene()->clear();
}
Re: Error code after inheriting QGraphicsView
If the lifespan of the scene is tied to the lifespan of the view then the easiest way is to make the scene a dynamically allocated object with its parent set to the view. Then you don't have to clear the scene because the scene's destructor will do it for you. Maybe the problem will go away then. Also, what is causing the view to be deleted?
Re: Error code after inheriting QGraphicsView
Quote:
Originally Posted by
wysota
If the lifespan of the scene is tied to the lifespan of the view then the easiest way is to make the scene a dynamically allocated object with its parent set to the view. Then you don't have to clear the scene because the scene's destructor will do it for you. Maybe the problem will go away then. Also, what is causing the view to be deleted?
That was it! I did just as you said and it worked perfectly. In fact, it is much simplier and logical to modify an existing widget this way, than to replace it. Thanks for all your help. I will provide the changed code for the others with similar problems:
Code:
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow
::MainWindow(QWidget *parent
) : QWidget(parent
), ui
(new Ui
::MainWindow){
ui->setupUi(this);
view = new GraphicsView(ui->widget); // <--- here
view->setScene(&scene); //
view->resize(ui->widget->size()); //
connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(close()));
connect(ui->loadButton, SIGNAL(clicked()), this, SLOT(loadImage()));
}
MainWindow::~MainWindow()
{
delete view;
delete ui;
}
void MainWindow::loadImage()
{
image.load(fileName);
scene.addPixmap(image);
view->loadImage(image);
}
Re: Error code after inheriting QGraphicsView
So what exactly did you change? Because if you mean line #7 of the above snippet then it's certainly not what I meant and it shouldn't have any influence on your application.
Re: Error code after inheriting QGraphicsView
Hmm, now I realized that when I was reading your post I saw "view" instead of "scene" in part about dynamic allocation. Nevertheless it somehow solved the problem with the exit code. Do you think that it was just a luck? Maybe there is another mistake?
And to answer your question: I just dynamically allocated memory for view object and I set wiget from the main form to be a parent for it.
Re: Error code after inheriting QGraphicsView
If you look inside setupUi(), that's exactly what was happening previously too.