PDA

View Full Version : QGraphicsSvgItem, problem with scaling (invalid bounding rect)



Józef Paczenko
20th March 2008, 12:10
Hello.
As I suprisingly noticed, calling scale() method on QGraphicsSvgItem doesn't change its bounding rect. To fix it, I made my own class inheriting from it which updates the bounding rect when needed. The problem is the Qt finds it somehow invalid, for example when i call the moveBy() method on the item, only the part of the item is moved. Furthermore, mouseReleaseEvent() catches only clicks in that area. what could be the reason of this behaviour?

Screenshot (http://img238.imageshack.us/img238/4761/qterrorfw1.png)

I'm quite sure the bounding rect returned is correct, I even checked with screen ruler and it turned out to be right.

Here is some code (I left only important parts):


class Card : public QGraphicsSvgItem {
Q_OBJECT

public:
Card(CardType type, CardValue value, QSvgRenderer * renderer);
void scale(qreal sx, qreal sy);
QRectF boundingRect() const;

signals:
void clicked(Card * card);

private:
QRectF * rect;

void mouseReleaseEvent(QGraphicsSceneMouseEvent * event);

};



Card::Card(CardType type, CardValue value, QSvgRenderer * renderer){
prepareGeometryChange();
this->rect = new QRectF(QGraphicsSvgItem::boundingRect());
scale(this->scaleRatio, this->scaleRatio);
}

void Card::scale(qreal sx, qreal sy){
this->rect->setWidth(this->rect->width()*sx);
this->rect->setHeight(this->rect->height()*sy);
QGraphicsSvgItem::scale(sx, sy);
}

QRectF Card::boundingRect() const {
return *(this->rect);
}

void Card::mouseReleaseEvent(QGraphicsSceneMouseEvent * event){
emit clicked(this);
}

and the slot connected to clicked():


void BoardWidget::cardClicked(Card * card) {
qDebug() << "Kliknieto" << *card << card->boundingRect();
card->moveBy(10, 10);
}

The bounding rect of the card in cardClicked() matches with the real size, its shape too. What could be the reason of the problem?

kusa
20th March 2008, 16:26
Hello.
The boundingRect() method returns the bounding rectangle in item coordinates, so it is not affected by transformations such as scale, rotation...
If you want to get the bounding rectangle in scene coordinates you have to use the family of methods mapToScene(...).

I hope this answers your question.

Regards,

Sebastien.

Józef Paczenko
22nd March 2008, 08:32
Ah. How it was possible I couldn't notice it back then... Thank you for your help.

qlands
8th June 2010, 08:58
Hi,

I have a question related to this post. I am writing a graphical application that require scale of graphic items. In the application the user drags and drops polygon from a toolbar (like Dia does). When the polygon lands into the scene it has an standard size. I need to implement the scale of the items. Im using the setScale function. The problem that I have is when user want to scale an already scaled item. For example if I scale an item to 2.0 the result is a item twice its original size, if I do 2.0 again the function uses the original polygon and not the scaled one.

I tried to work around the problem with the following code:


//Scaled polygon
QPolygonF spoly;

//One item in the scene
tnkPolygonSymbol *item;

//Gets one item from the scene
item = qgraphicsitem_cast<tnkPolygonSymbol *>(scenes[currentPage]->items()[0]);

//Scale the item to double
item->setScale(2.0);

//Gets the scaled item from the scene
spoly = item->mapToScene(item->polygon());

//Restores the scale to the original size
item->setScale(1.0);

//Replaces the items polygon with the scaled polygon
item->setPolygon(spoly);


However this does not work as the resulting polygon has different coordinate values than the original. The result of the process is shown in Image 1:
http://www.qlands.com/other_files/scene02.jpg

After the process the bounding rectangle is double is size but the resized polygon is away from its bounding rectangle. This may happen because the coordinate values of the spoly are not the same as the item in the scene. I tried to set the coordinates of spoly with moveTo, CeterOn, etc and nothing seems to work.

Any ideas will be appreciated.

Carlos.