positioning QGraphicsSvgItem's center on a position. - c++

I have a created a QGraphicsSvgItem on a QGraphicsScene with size 48x48.
I want to set it's center on x= 50 and y= 50 of the QGraphicsScene(By default QGraphicsScene position the top left corner of the svg item).
I have inherited QGraphicsSvgItem and reimplemented its paint function and then applied a translate operation at x= -24 y = -24,But then it shows 1/4 right bottom shape of the svg item visible.
so please suggest ,how to align the center of svgitem at x=50 ,y =50

A QGraphicsItem has its local top left at (0,0) by default. However, if you're inheriting from QGraphicsItem, you can change it, so that (0,0) is the centre of the item.
This is handled by the boundingRect() function. If you have an item that is of height and width 50, the default bounding rect would be returning (0,0,50,50) for (x,y,w,h).
To make the local centre (0,0) override the boundingRect function to return (-25, -25, 50, 50).
QRectF boundingRect() const
{
return QRectF(-25, -25, 50, 50);
}
Then, to centre the item in the scene at (50,50), you just need to set the item's position to that coordinate
item->setPos(50, 50);

Need to reimplement the paint method of the QGraphicsSvgItem also
QRectF boundingRect() const
{
return QRectF(-24,-24,48,48);
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->translate(-24,-24);
QGraphicsSvgItem::paint(painter,option,widget);
}

Related

How to set the icon when QTabBar is set to east or west?

I want to rotate the content of tab in a verticle QTabBar. So I tried to inherit QProxyStyle, and override the drawItemText func, it works well.But when I tried to rotate the icon to show the pixmap by override the drawItemPixmap func
void myTabStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,const QPixmap &pixmap) const
{
painter->save();
painter->rotate(90);
QRect r = QRect(0,0,rect.width(),rect.height());
QProxyStyle::drawItemPixmap(painter,r,Qt::AlignRight,pixmap);
painter->restore();
}
no matter how I translate the painter,or set clip rect by ClipRect(r,Qt::NoClip) ,the pix map just show in the middle of tab,if I translate the painter to left side,there will be just a part of pixmap in the middle.I guess the qt clip pixmap. How to solve this problem.

Drawing Text In a QGraphicsWidget::paint function

I'm trying to draw text inside a qgraphicswidget. The scale of the scene is -180 to 180 in the horizontal and -90 to +90 in the vertical (it's a world map).
When i zoom in to individual items on the map, i want some text to show up. My code for the paint function of one particular item looks like this:
void AirportGraphicsWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
QPen pen;
pen.setStyle(Qt::PenStyle::NoPen);
painter->setBrush(Qt::lightGray);
painter->setPen(pen);
if (m_curr_lod <= LevelOfDetail::MEDIUM) {
painter->setBrush(QColor(206, 211, 219));
painter->drawEllipse(m_airport_significance_rect);
} else if(m_curr_lod == LevelOfDetail::HIGH) {
painter->setBrush(QColor(56, 55, 52, 150));
painter->drawEllipse(m_airport_boundary);
DrawRunways(painter, option, widget);
} else {
painter->setBrush(QColor(56, 55, 52));
painter->drawEllipse(m_airport_boundary);
pen.setStyle(Qt::PenStyle::SolidLine);
pen.setColor(Qt::black);
painter->setPen(pen);
DrawRunways(painter, option, widget);
DrawILS(painter, option, widget);
DrawCOM(painter, option, widget);
QPen pen;
pen.setStyle(Qt::PenStyle::SolidLine);
pen.setColor(Qt::white);
pen.setWidth(0);
QFont font("Arial");
font.setPixelSize(15);
painter->setFont(font);
painter->setPen(pen);
painter->drawText(m_airport_boundary, "TEST");
}
}
The drawText call does not seem to be working at all. My scale at this zoom level is very small. The m_airport_boundary QRectF variable has the following values:
{ x = -0.010286252057250001, y = -0.010286252057250001, width = 0.020572504114500002, height = 0.020572504114500002 }
the drawing of the m_airport_boundary rect is visible so I know im trying to draw in the correct location. Can anyone tell me what I'm doing wrong?
Screenshot of what is drawing... The dark circle is the m_airport_boundary ellipse. Green things are a result of DrawILS and the blue circle is DrawCOM
The current QTransform scale is affecting the font size.
I suggest to calculate the text position in screen space, reset the transform and then call drawText().
Here is a snippet (suppose you want to draw at the center):
QPointF pos = m_airport_boundary.center();
QTransform t = painter->transform();
painter->resetTransform();
pos = t.map(pos);
painter->drawText(pos, "TEST");

paint qgraphicsitem in front of its parent

I want to paint a round rectangle using the paint function in QGraphicsItem, I have a parent item and I want to paint its child in front of it, but I don't know how to do it?
And I have another problem, I want to list this items base on their parent position, but positions are static, how can I position items based on the parent position?
My paint function :
void flipedWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *w)
{
Q_UNUSED(w)
Q_UNUSED(option)
painter->setPen(Qt::NoPen);
QBrush *brush;
if(!m_color.isEmpty())
brush = new QBrush(QColor(m_color)); // set background color
else
brush = new QBrush("#cccccc");
painter->setBrush(*brush);
painter->drawRoundedRect(boundingRect(), 10, 10);
delete brush;
}

QT QGraphicsScene Drawing Arc

I have a question about drawing specific arc on a scene. I have this information about arc:
Starting Koordinates,
Start Angle,
End Angle ,
Radius.
But I can't use them efficently with QPainter. Actually I tried QPainterPath to use shape to show on QGraphicsScene with addPath("") but I can't use function properly. My questions are about how to use this infortmation to draw arc and how to show it on my graphic scene.
You can use a QGraphicsEllipseItem to add ellipses, circles, and segments/arcs to a QGraphicsScene.
Try
QGraphicsEllipseItem* item = new QGraphicsEllipseItem(x, y, width, height);
item->setStartAngle(startAngle);
item->setSpanAngle(endAngle - startAngle);
scene->addItem(item);
Unfortunately, QGraphicsEllipseItem only supports QPainter::drawEllipse() and QPainter::drawPie() - the latter can be used to draw arcs, but has the side effect that there is always a line drawn from the start and the end of the arc to the center.
If you require a true arc, you can e.g. subclass QGraphicsEllipseItem and override the paint() method:
class QGraphicsArcItem : public QGraphicsEllipseItem {
public:
QGraphicsArcItem ( qreal x, qreal y, qreal width, qreal height, QGraphicsItem * parent = 0 ) :
QGraphicsEllipseItem(x, y, width, height, parent) {
}
protected:
void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
painter->setPen(pen());
painter->setBrush(brush());
painter->drawArc(rect(), startAngle(), spanAngle());
// if (option->state & QStyle::State_Selected)
// qt_graphicsItem_highlightSelected(this, painter, option);
}
};
You then still need to handle the item highlighting, unfortunately qt_graphicsItem_highlightSelected is a static function defined inside the Qt library.

QGraphicsView and QGraphicsItem: don´t scale item when scaling the view rect

I am using Qt´s QGraphicsView - and QGraphicsItem-subclasses.
is there a way to not scale the graphical representation of the item in the view when the view rectangle is changed, e.g. when zooming in. The default behavior is that my items scale in relation to my view rectangle.
I would like to visualize 2d points which should be represented by a thin rectangle which should not scale when zooming in the view. See a typical 3d modelling software for reference where vertex points are always shown at the same size.
Thanks!
Set the QGraphicItem's flag QGraphicsItem::ItemIgnoresTransformations to true does not work for you?
I got into the same problem, and it took me a while to figure it out. This is how I solved it.
Extend a QGraphicsItem class, override paint().
Inside the paint(), reset the transformation's scaling factor to 1(which are m11 and m22), and save the m11(x scaling factor) and m22(y scaling factor) before the reset.
Then, draw like you would normally do but multiply your x with m11 and y with m22. This avoids drawing with the default transformation, but explicitly calculates the positions according to the scene's transformation.
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
QTransform t = painter->transform();
qreal m11 = t.m11(), m22 = t.m22();
painter->save(); // save painter state
painter->setTransform(QTransform(1, t.m12(), t.m13(),
t.m21(), 1, t.m23(), t.m31(),
t.m32(), t.m33()));
int x = 0, y = 0; // item's coordinates
painter->drawText(x*m11, y*m22, "Text"); // the text itself will not be scaled, but when the scene is transformed, this text will still anchor correctly
painter->restore(); // restore painter state
}
The following code block is drawing with default transformation
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
int x = 0, y = 0;
painter->drawText(x, y, "Text");
}
You can try both to see the difference. Hope this helps.
How about this:
#include <QtGui/QApplication>
#include <QtGui/QGraphicsScene>
#include <QtGui/QGraphicsView>
#include <QtGui/QGraphicsRectItem>
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
scene.addText("Hello, world!");
QRect rect(50, 50, 100, 100);
QGraphicsRectItem* recti = scene.addRect(rect);
QGraphicsView view(&scene);
// Set scale for the view
view.scale(10.0, 5.0);
// Set the inverse transformation for the item
recti->setTransform(view.transform().inverted());
view.show();
return app.exec();
}
As you can see the text is scaled up but the rectangle is not. Note that this does not only prevent the scaling for the rectangle but and other transformation.
The following solution worked perfectly for me:
void MyDerivedQGraphicsItem::paint(QPainter *painter, const StyleOptionGraphicsItem *option, QWidget *widget)
{
double scaleValue = scale()/painter->transform().m11();
painter->save();
painter->scale(scaleValue, scaleValue);
painter->drawText(...);
painter->restore();
...
}
We can also multiply the scaleValue by other mesures we want to keep its size constant outside the save/restore environment.
QPointF ref(500, 500);
QPointF vector = scaleValue * QPointF(100, 100);
painter->drawLine(ref+vector, ref-vector);
I found that if I derive a new class and reimpliment the paint function I can do
void MyDerivedQGraphicsItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
double scaleValue = scale();
double scaleX = painter->transform().m11();
setScale(scaleValue / scaleX);
QGraphicsSvgItem::paint(painter,option,widget);
}
This is the best way of doing it that I have found so far, but I am still tinkering around.