Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Constant size QGraphicsPixmapItem position problem

Constant size QGraphicsPixmapItem position problem

Scheduled Pinned Locked Moved General and Desktop
8 Posts 2 Posters 3.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    N4k1m
    wrote on last edited by
    #1

    Hi,

    First, sorry for my English, i'm french.

    I'm facing a problem with the position of a constant size QGraphicsPixmapItem when the view is scaled.

    Like on http://www.flightradar24.com/, I would like to display planes (constant size QGraphicsPixmapItems) on a "aeroport map" that can be rescaled.

    To do this, I've a basic QGraphicsScene that contains a QGraphicsPixmapItem (picture) that represents the "aeroport map". On this map, I've planes, instances of QGraphicsPixmapItem class, with the flag QGraphicsItem::ItemIgnoresTransformations set. I've extended the QGraphicsView class and overrided the wheelEvent method to implement a zooming function with the mouse wheel.

    The problem appears when I'm zooming --> The planes move. The position of the center of the plane change when I zoom in or out.

    Plane on the track :
    https://www.dropbox.com/s/6r6utd5o75d0evl/plane1.png?dl=0

    Plane move when zooming out (or in)
    https://www.dropbox.com/s/xgb97o8b1n1zczo/plane2.png?dl=0

    What I have to do for the center of the plane stay at the same position when I'm zooming ?

    In the documentation, i read this about the flag QGraphicsItem::ItemIgnoresTransformations : "When set, the item's view geometry and scene geometry will be maintained separately. You must call deviceTransform() to map coordinates and detect collisions in the view." --> but I don't understand when/where to invoke it and how to use it.

    Here is my simple code:

    @
    class PlaneGraphicsItem : public QGraphicsPixmapItem
    {
    public:

        explicit PlaneGraphicsItem(QGraphicsItem* parent = NULL);
        virtual ~PlaneGraphicsItem(void);
    

    };

    PlaneGraphicsItem::PlaneGraphicsItem(QGraphicsItem* parent) :
    QGraphicsPixmapItem(QPixmap(":/images/plane"), parent)
    {
    this->setFlag(QGraphicsItem::ItemIsMovable);
    this->setFlag(QGraphicsItem::ItemIgnoresTransformations);

    this->setTransformOriginPoint(this->boundingRect().center());
    

    }

    PlaneGraphicsItem::~PlaneGraphicsItem(void){}
    @

    @
    class MapGraphicsView : public QGraphicsView
    {
    Q_OBJECT

    public:
    
        explicit MapGraphicsView(QWidget* parent = NULL);
        virtual ~MapGraphicsView(void);
    
    protected:
        virtual void wheelEvent(QWheelEvent* event);
    
    private:
        void scaleXY(double factor);
    
    protected:
    
        double _factor;
    

    };

    MapGraphicsView::MapGraphicsView(QWidget* parent) :
    QGraphicsView(parent), _factor(1.2)
    {
    [...]

    this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    this->setDragMode(ScrollHandDrag);
    

    }

    MapGraphicsView::~MapGraphicsView(void) {}

    void MapGraphicsView::wheelEvent(QWheelEvent* event)
    {
    // Zoom in
    if (event->delta() > 0)
    this->scaleXY(this->_factor);
    // Zoom out
    else
    this->scaleXY(1.0/this->_factor);
    }

    void MapGraphicsView::scaleXY(double factor)
    {
    this->scale(factor, factor);
    }
    @

    @
    MainWidget::MainWidget(QWidget* parent) :
    QWidget(parent), ui(new Ui::MainWidget),
    _scene(NULL), _mapTrack(NULL), _planeItem(NULL)
    {
    this->ui->setupUi(this);

    // Create items
    this->_mapTrack = new QGraphicsPixmapItem(QPixmap(":/images/map"));
    this->_planeItem = new PlaneGraphicsItem(this->_mapTrack);
    
    // Create scene
    this->_scene = new QGraphicsScene(this);
    
    // Populate scene
    this->_scene->addItem(this->_mapTrack);
    
    this->ui->mapGraphicsView->setScene(this->_scene);
    

    }
    @

    Thanks for your help.
    Best regards,
    Xavier Mawet

    1 Reply Last reply
    0
    • N Offline
      N Offline
      N4k1m
      wrote on last edited by
      #2

      Up...

      1 Reply Last reply
      0
      • N Offline
        N Offline
        N4k1m
        wrote on last edited by
        #3

        Up ...

        1 Reply Last reply
        0
        • R Offline
          R Offline
          Rondog
          wrote on last edited by
          #4

          I suspect the problem is related to changing the size of the image (the plane in this case) relative to the graphics scene. Your goal is to keep the graphics item the same size so therefore you must adjust the position of the graphics item on the graphics scene.

          I had a similar problem but from a different cause (I wanted to adjust the size of the graphics images without having them move on the graphics scene). My solution was to use the center of the graphics image and adjust the position as the size changed. The item data 'ITEM_POS_FIELD' from the example represents the center coordinates of the image.

          @
          for(item_iter = d_item_images.begin();item_iter != d_item_images.end();++item_iter)
          {
          center_target = (*item_iter)->data(ITEM_POS_FIELD).toPointF();
          center_offset = QPointF(d_item_size.width()/2,d_item_size.height()/2);

          center_target.setX(center_target.x() - center_offset.x());
          center_target.setY(center_target.y() - center_offset.y());

          (*item_iter)->setPos(center_target);
          }
          @

          1 Reply Last reply
          0
          • N Offline
            N Offline
            N4k1m
            wrote on last edited by
            #5

            Thanks for your help but it it didn't solve my problem.

            1 Reply Last reply
            0
            • R Offline
              R Offline
              Rondog
              wrote on last edited by
              #6

              This option could be contributing to your problem:

              @
              this->setFlag(QGraphicsItem::ItemIgnoresTransformations);
              @

              I had a look at what I did for this. It is not too different from what you have in some regards but I didn't use 'QGraphicsItem::ItemIgnoresTransformations'.

              If you do set this flag (QGraphicsItem::ItemIgnoresTransformations) for the graphicsitem I believe you need to manually do the transformations or position adjustments yourself. I don't see any of this in your example code.

              1 Reply Last reply
              0
              • N Offline
                N Offline
                N4k1m
                wrote on last edited by
                #7

                This is the flag I used (class PlaneGraphicsItem, line 13). And when I zoom in/out the center of the plane doesn't stay at the same position. This is my problem.

                But in the documentation, i read this about the flag QGraphicsItem::ItemIgnoresTransformations : “When set, the item’s view geometry and scene geometry will be maintained separately.You must call deviceTransform() to map coordinates and detect collisions in the view.” —> but I don’t understand when/where to invoke it and how to use it.

                I see : " this thread on stackoverflow":http://stackoverflow.com/questions/1719694/getting-the-bounding-box-of-a-constant-size-item-in-qt-graphics-views but I don't know how to incorporate it in my code (and where ???)

                1 Reply Last reply
                0
                • R Offline
                  R Offline
                  Rondog
                  wrote on last edited by
                  #8

                  You would need to perform the manual calculations after anything that changes the viewport or viewport scale. Probably in here:

                  @
                  void MapGraphicsView::scaleXY(double factor)
                  {
                  this->scale(factor, factor);

                      // code here.  See stackoverflow
                  }
                  

                  @

                  The link on stackoverflow seemed to have a solution and a mention of using an 'inverted vp_trans' matrix. The idea is to simply rearrange the data something like this:

                  @
                  | a | b | c |
                  | d | e | f |
                  | g | h | i |
                  @

                  to

                  @
                  | a | d | g |
                  | b | e | h |
                  | c | f | i |
                  @

                  The QTransform.transposed() function does this I believe.

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved