PDA

View Full Version : Updating Foreground for QGraphicsView



tts80
2nd January 2007, 04:23
Hi all,

I am writing a graph editor that allows user to add nodes and edges. The first node is added by left clicking on the viewport and subsequence clicks will added a node and an edge that links the new node to the previous node. I would like to draw a line interactively when the user moves the mouse around (not holding down any button) to help visualize the edge that will be created at different node position.

I have subclassed the QGraphicsView and overridden the drawForeground and mouseMoveEvent. I have also set the mouse tracking to true. But the screen just doesn't seem to update itself properly. Below is the code for drawForeground and mouseMoveEvent. Hope someone can advice on this. Thanks.


void MapView::mouseMoveEvent(QMouseEvent *event)
{
if(editing)
{
newPos = mapToScene(event->pos());
update();
}

void MapView::drawForeground(QPainter *painter, const QRectF &rect)
{
if(editing)
{
painter->setPen(Qt::white);
painter->drawLine(oldPos, newPos);
}
}


Thuan Seah Tan

aamer4yu
2nd January 2007, 08:53
You are simply drawing lines in the foreground... where are you erasing the old lines ??
u need to implement the rubber banding technique to make the line look moving...

also I think it will be better if you implement the edges as items... it would make more sense and may make the work easier... u can think of edge as an entity, a graphics item..

also implementing the edge as Graphics item will make you maintain the edge in scene itself without the overhead of passing information about the edges to the view .
hope this helps :)

tts80
2nd January 2007, 23:08
Thanks for the suggestions, aamer4yu. In fact, I have already implemented my nodes and edges as graphicsitem which did indeed help to simply things a lot. The problem I am having now is that the window only updates itself after window switch (e.g. Alt tab to some other window and returning to my application). Surprisely, I found that calling QGraphicsScene update instead of the update of QGraphicsView actually updates the window properly.

Only problem is that only a bounding rect region containing all graphics items in the scene is updated. Is that where the rubber band technique comes in? At the moment I simply call QGraphicsScene->update(QGraphicsScene->sceneRect()) which updates the entire scene. Not very efficient way to do things I suppose.

Thuan Seah

Gopala Krishna
3rd January 2007, 03:36
Only problem is that only a bounding rect region containing all graphics items in the scene is updated. Is that where the rubber band technique comes in? At the moment I simply call QGraphicsScene->update(QGraphicsScene->sceneRect()) which updates the entire scene. Not very efficient way to do things I suppose.
Thuan Seah

You can use QRubberBand with its parent being QGraphicsView->viewport() and then call setGeometry() appropriately while providing feedback of line being drawn. You need not update scene in that case. See QRubberBand's doc for more details.

aamer4yu
4th January 2007, 07:35
well if u are implementing the edge as item, u need not worry about the rubber banding. what u need to do is just change the shape of the item on mouse movements.
for this u can maintain a list of edges in contact with a node, now when the node moves, u change the shape of edges connected to it and call the update to items if necessary.
As for the bounding rect u can return the rectangle covered by the line.
for shape, override the shape() method... and be sure to call prepareGeometryChange() before changing the shape...

try it, hope it will solve the prob

Gopala Krishna
4th January 2007, 15:28
Just one more tip for you. I guess you can use already existing QGraphicsLineItem or a class derived from it for edges which simplies a lot. You just need to call QGraphicsLineItem::setLine(QLineF line) method and no need to worry about geometry at all. Hope this helps.