PDA

View Full Version : add points/path to QGraphicsView



szisziszilvi
12th January 2011, 14:19
Hello,

I'm on to learn the usage of QGraphicsView, and the main goal would be to draw diagrams of some data, so the best would be if I could give points (or better dreams: paths) to the object.

Now this works fine:


QGraphicsScene *scene = new QGraphicsScene;
scene->addLine(0,0,50,30,QPen(QColor(0,0,0)));
scene->addEllipse(10,20,50,60);
ui->graphicsView->setScene(scene);


but I can't figure out how could I add simple points, or how to combine it with eg. QPainter. Or if I'm rihgt there would be a way through addItem, but I'm not very familiar with it's logic, and the examples in the Help are too complicated to avoid losting in the forest.

Regards

JohannesMunk
12th January 2011, 16:41
Hello Szilvi!

Have you considered using qwt (http://qwt.sourceforge.net/) to draw diagrams?

If you insist on doing it yourself in a graphicsview, create a class derived from QGraphicsItem and reimplement the paint function. The paint function recieves a pointer to a painter, which you can use to draw your diagram. If you have calculated the diagram-points you can draw them using drawPolyline or drawPoints.

HIH

Johannes

szisziszilvi
13th January 2011, 08:39
Yes, actually I tried to use this qwt, I downloaded, but somehow failed to install, I just couldn't reach it. But yes, you are far right that it could be better. Anyway it is never too bad for a beginner to learn the logic of the whole system.
Do I understand your idea well? Like this:

QGraphicsItemChild gic;
QPainter *painter;
painter.drawPoints(...); //(ect.)
gic.paint(painter);
QGraphicsScene *scene = new QGraphicsScene;
scene->addItem(gic);
Well, something must be not clear for me. Cheking the Help I can't see how could I calculate the coordinates themselves outside the reimplementation. Inside the reimplementation they suggest:

painter->drawRoundedRect(-10, -10, 20, 20, 5, 5);

But in this case the coordinates must be given inside.

Another question: if I create a clas derived for QGraphicsItem, and try to use that in the addItem function, that will give an error, won't it?

JohannesMunk
13th January 2011, 10:10
Hi Szilvi!

No, sorry to disappoint, but you didn't get it right :-> Creating a subclass and reimplementing a function looks very different! I recommend reading a c++ book first!



class Diagram : public QGraphicsItem
{
public:
Diagram() {}

QRectF boundingRect() const{ return QRectF(0, 0, 50, 50); }

void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
painter->drawRect(boundingRect());
painter->drawPolyline(...)
}
};


Now you can create an instance of this diagram-class and add it to the scene.



Diagram d = new Diagram();
scene->addItem(d);


You might want to pass the data as argument to its constructor or some setup-function.

This works as follows: The scene knows, that all its items are QGraphicItems. When it needs to redraw an item it simply calls its paint-method. And as we reimplemented that paint-method in our derived class, our code gets called.

HIH

Johannes

szisziszilvi
13th January 2011, 10:44
Yes, in my example I used a fake type: QGraphicsItemChild, where the reimplementation would be done.
So from your suggestion it would be like this:
there would be a member variable like
QRect bRect;
there would be a public member in Diagram:
void setBoundingRect(int x1,int y1,int x2,int y2){bRect = QRect(x1,y1,x2,y2);}
from yours the line: QRectF boundingRect() const{ return QRectF(0, 0, 50, 50); } turns to
QRectF boundingRect() const{ return bRect; }

so the bRect can be set from outside, and then at usage:

Diagram d = new Diagram;
d.setBoundingRect(1,2,3,4);
scene->addItem(d);

And here addItem calls the paint method by default? But for what QPainter object? Doesn't there should be a QPainter somewhere?

JohannesMunk
13th January 2011, 11:10
Hi!

You should probably not set the boundingRect directly, but calculate it by how much space your diagram requires. But of course you can also do it the other way around and set the boundingRect from the outside and adapt the scale of your diagram accordingly. Depends on what you want to achieve.

addItem doesn't call paint. It just adds the item to an internal list of graphic items of the scene. Now whenever the view or the scene decides that something needs to be repainted then the paint method is being called. And it is the scene/view that initializes and passes the painter object to your code. No need to worry about that.

Joh

szisziszilvi
13th January 2011, 13:35
all right, thank you a lot, I'll come back soon with the errors... :)
but honestly thanks, I think now I get it. off to try.

Added after 6 minutes:

Bearhug for JohannesMunk! :D

For some similarly beginner's interest the whole code together:
the derived class declaration:

class myQGraphichsItem : public QGraphicsItem
{
private:
QRect bRect;
public:
myQGraphichsItem();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const{ return bRect; }
void setBoundingRect(int x1,int y1,int x2,int y2){bRect = QRect(x1,y1,x2,y2);}
};
the paint method reimplemented:

void myQGraphichsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawRect(boundingRect());
}
in useage:

QGraphicsScene *scene = new QGraphicsScene;
myQGraphichsItem *mgi = new myQGraphichsItem;
mgi->setBoundingRect(30,60,90,100);
scene->addItem(mgi);
ui->graphicsView->setScene(scene);