PDA

View Full Version : Scale independent QGraphicsItem



Twoslick
5th March 2010, 19:56
I'm trying to represent a map using a QGraphicsScene. I've set up a custom view, and implemented zooming functionality. So far, I've gotten basic polygons and lines working but have come across a snag when trying to represent points or labels.

Since there is no "point item" in the API, I'm using QGraphicsEllipseItem to represent points on the map. My problem is that these are effected by the scale, so they completely disappear if I zoom out very far. This also occurs for any text labels I place in the scene.

Is there a way to make custom graphics items that always draw with a fixed size? I want to avoid specifically drawing anything in the view since I may have multiple views into the scene (although I may consider putting text labels there).


Update: I've come up with a solution for drawing points, but I'm not sure if this is the best method. This sets a minimum size when drawing on the screen. As such, the point will never disappear from the view when zoomed out.

Note: This example code hasn't been optimized for drawing speed, since each point would be required to calculate the drawing scale.



#pragma once
#include <QGraphicsItem>

class GraphicsPointItem : public QGraphicsItem
{
private:
static qreal sRadius;
static qreal sDiameter;

public:
QRectF boundingRect() const
{
return QRectF(-sRadius, -sRadius, sDiameter, sDiameter);
}

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QRectF objectRect = boundingRect();
QRectF mappedRect = painter->transform().mapRect(objectRect);

qreal widthRatio = objectRect.width() / mappedRect.width();

if (widthRatio > 1) // Stop the point from shrinking after zooming out
painter->scale(widthRatio, objectRect.height() / mappedRect.height());

QBrush brush(Qt::black);
painter->setBrush(brush);
painter->setPen(Qt::NoPen);

painter->drawEllipse(-sRadius, -sRadius, sDiameter, sDiameter);
}
};

qreal GraphicsPointItem::sDiameter = 4;
qreal GraphicsPointItem::sRadius = 2;

Urthas
24th March 2010, 05:56
May I ask why in your boundingRect() method, you use negative co-ordinates? I'm new to Qt and quite lost on little things like that. :(

girishgowda
24th March 2010, 06:08
Hi,

You seem to be scaling your QGraphicsEllipseItem also in the paint().
Please see if you can avoid scaling of the points and labels - depending on your requirement of when you want to show the points and labels.

If my understanding is correct, then the points and labels would have to scale up when your map is scaled-up.

Regards
Girish

aamer4yu
24th March 2010, 06:59
Did you come across QGraphicsItem::ItemIgnoresTransformations :rolleyes:
May be thats what you need for your ellipse item :)