PDA

View Full Version : Drawing a fixed-sized shape at mouse press position on QGraphicsView



lain
8th April 2011, 10:27
Hi, I am trying to write an application to manipulate images using the GraphicsView framework.
I derived QGraphicsPixmapItem to display an image and reimplemented mousePressEvent() to draw a circle at the mouse press position on the image.
I want the image to automatically fit to the window when the view is resized while keeping the circle size fixed.
So I set the ItemIgnoresTransformations flag in order not to resize the circle, and converted the mouse press position to the view coordinate before setting it as the circle position.
But the position of the drawn circle is deviated from the mouse press position.

The following is the simplified code of mine.


#include <QApplication>
#include <QtCore>
#include <QtGui>

class MyItem : public QGraphicsPixmapItem
{
public:
MyItem(QGraphicsView *v): view(v)
{
circle = new QGraphicsPathItem(this);
circle->setFlag(QGraphicsItem::ItemIgnoresTransformations) ;
circle->hide();
}

protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent * event)
{
QPointF pos_view = view->mapFromScene(mapToScene(event->pos()));
QPainterPath path;
const int Radius = 100;
path.addEllipse(pos_view, Radius, Radius);
circle->setPath(path);
circle->show();
update();
}

private:
QGraphicsView *view;
QGraphicsPathItem *circle;
};

class MainWindow : public QMainWindow
{
public:
MainWindow()
{
view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlw aysOff);
view.setVerticalScrollBarPolicy(Qt::ScrollBarAlway sOff);
view.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

setCentralWidget(&view);
setWindowTitle(tr("Image Viewer"));

item = new MyItem(&view);
item->setPixmap(QPixmap("test.tif"));
item->setTransformationMode(Qt::SmoothTransformation);

scene.addItem(item);
view.setScene(&scene);
}

protected:
virtual void resizeEvent(QResizeEvent *event)
{
view.fitInView(item, Qt::KeepAspectRatio);
}

private:
QGraphicsView view;
QGraphicsScene scene;
MyItem *item;
};


int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mw;
mw.show();
mw.resize(500, 700);
return app.exec();
}


Could someone tell me what is wrong with this?

high_flyer
12th April 2011, 16:57
Why do you map to and back from scene coordinates?
You are taking your item coordinates, map them to scene coords, and than map that to view coords, and you give these coords to the item to draw!
The position you get from the event is in item coordinates, and you are in an item, so just use the position you get from the event.

lain
13th April 2011, 02:54
Hi, thank you very much for reply.


You are taking your item coordinates, map them to scene coords, and than map that to view coords, and you give these coords to the item to draw!
The position you get from the event is in item coordinates, and you are in an item, so just use the position you get from the event.

But if I just use the position given from the event, the item is not drawn at the mouse press position because I set QGraphicsItem::ItemIgnoresTransformations flag of the item to prevent it from resizing with window...
Is there any better way to keep the item size to fixed number of pixels?

high_flyer
13th April 2011, 09:24
the item is not drawn at the mouse press position because I set QGraphicsItem::ItemIgnoresTransformations flag
I don't see why this should matter?
The flag means that the item doesn't scale.
But its position stays the same in the parent coordinates, and the item coordinates remain the item coordinates.

lain
13th April 2011, 11:22
Thank you again for your reply.


I don't see why this should matter?
The flag means that the item doesn't scale.
But its position stays the same in the parent coordinates, and the item coordinates remain the item coordinates.

The item is drawn at the mouse press position if I don't set the QGraphicsItem::ItemIgnoresTransformations, but NOT if the flag is set...
I would appreciate it if you could confirm this using my code above with any image named test.tif.

lain
24th June 2011, 12:07
I've found a kind of solution.
If I make the item a direct child of the scene, it is drawn at the mouse press position.
Do I need to define the transformation matrix by myself to make the item a child of another item?
Seems tricky...