Fixed the position of QGraphicsItem, without changing the behavior of other QGraphicsItem objects in the scene

This question is related to: Forcing QGraphicsItem to post

I want to have QGraphicsItem in a fixed place when moving around the scene.

The proposed solution is to override the void paintEvent(QPaintEvent*) subclass of QGraphicsView .

 void MyGraphicsView::paintEvent(QPaintEvent*) { QPointF scenePos = mapToScene(0,0); // map viewport top-left corner to scene myItem->setPos(scenePos); } 

However, the problem is that I want everything else in the scene to remain intact, i.e. if I zoom in or move, I want all the other QGraphicsItems behave like the default.

One of the weak ways to solve this problem is to call void QGraphicsView::paintEvent(QPaintEvent*) from void MyGraphicsView::paintEvent(QPaintEvent*) .

 void MyGraphicsView::paintEvent(QPaintEvent* event) { QGraphicsView::paintEvent(event); QPointF scenePos = mapToScene(0,0); // map viewport top-left corner to scene myItem->setPos(scenePos); } 

However, this adds flicker to my_item , as it was positioned first using QGraphicsView::paintEvent(event); and then using the added code

 QPointF scenePos = mapToScene(0,0); // map viewport top-left corner to scene myItem->setPos(scenePos); 

The question is, should I void MyGraphicsView::paintEvent(QPaintEvent*) from scratch and write the code for both the desired myItem behavior and the default for all other QGraphicsItems , or is there an easier way to do this?

Thanks.

+2
c ++ qt qgraphicsscene qgraphicsview qgraphicsitem
source share
1 answer

I think this is what you are looking for:

http://qt-project.org/doc/qt-4.8/qgraphicsitem.html#setFlag

QGraphicsItem::ItemIgnoresTransformations

Description from the docs:

An element ignores inherited transformations (i.e. its position is still tied to its parent element, but ignoring rotation, image rotation, scaling, or shifting is ignored). This flag is useful for saving text label elements horizontally and unscaled, so they will be readable if the view is converted. When set, presentation geometry and scene geometry will be supported separately. You must call deviceTransform () to match the coordinates and detect collisions in the view. By default, this flag is disabled. This flag was introduced in Qt 4.3. Note. When this flag is set, you can scale the object itself, and this scale transformation will affect the children of the element.

You may also want to parent everything that makes the pan to something else. Then you move or scale or rotate one graphic group to influence everything except your "inexpressible" objects.

https://qt-project.org/doc/qt-4.8/graphicsview.html#the-graphics-view-coordinate-system

https://qt-project.org/doc/qt-4.8/painting-transformations.html (a cool example, although it really doesn't show this function)

http://qt-project.org/doc/qt-4.8/demos-chip.html (great example of using QGraphicsView )

Hope this helps.

EDIT:

An example showing how you can achieve a static level with parenting:

main.cpp

 #include <QApplication> #include "mygraphicsview.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MyGraphicsView w; w.show(); return a.exec(); } 

mygraphicsview.h

 #ifndef MYGRAPHICSVIEW_H #define MYGRAPHICSVIEW_H #include <QGraphicsView> #include <QGraphicsItemGroup> #include <QMouseEvent> class MyGraphicsView : public QGraphicsView { Q_OBJECT public: MyGraphicsView(QWidget *parent = 0); ~MyGraphicsView(); public slots: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); private: bool down; QPointF m_last_pos; QGraphicsItemGroup * m_group; }; #endif // MYGRAPHICSVIEW_H 

mygraphicsview.cpp

 #include "mygraphicsview.h" #include <QGraphicsItem> #include <QGraphicsEllipseItem> #include <QGraphicsTextItem> MyGraphicsView::MyGraphicsView(QWidget *parent) : QGraphicsView(parent) { down = false; this->setScene(new QGraphicsScene); // Anything not added to the "group" will stay put this->scene()->addEllipse(20, 20, 50, 50); this->scene()->addEllipse(180, 180, 50, 50); this->scene()->addText("Click and drag with the mouse to move only the tiny dots."); // This group will receive all transformations m_group = new QGraphicsItemGroup; for(int r = 0; r < 20; r ++) { for(int c = 0; c < 20; c++) { if(c % 5 == 0 && r % 5 == 0) { QGraphicsTextItem * txt = new QGraphicsTextItem(QString::number(r) + "," + QString::number(c)); m_group->addToGroup(txt); txt->setPos(r*100, c*100); } m_group->addToGroup(new QGraphicsEllipseItem(r *100, c*100, 5, 5)); } } this->scene()->addItem(m_group); } MyGraphicsView::~MyGraphicsView() { } void MyGraphicsView::mousePressEvent(QMouseEvent *event) { m_last_pos = mapToScene(event->pos()); down = true; } void MyGraphicsView::mouseReleaseEvent(QMouseEvent *) { down = false; } void MyGraphicsView::mouseMoveEvent(QMouseEvent *event) { if(down) { QPointF temp = mapToScene(event->pos()); QPointF delta = temp - m_last_pos; m_last_pos = temp; // Apply transformation to the group, not the scene! m_group->translate(delta.x(), delta.y()); } } 
+4
source share

All Articles