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. QItems alignment problem when using scaling with custom graphicsView and graphicsScene
Qt 6.11 is out! See what's new in the release blog

QItems alignment problem when using scaling with custom graphicsView and graphicsScene

Scheduled Pinned Locked Moved General and Desktop
5 Posts 1 Posters 3.2k 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.
  • L Offline
    L Offline
    lugemononeurone
    wrote on last edited by
    #1

    Hi,

    I'm developping on WinXP, Visual Studio 2008 and Qt5. I'm a newbie in Qt

    I am trying to visualize an image. I must be able to zoom in/out in that image. When the cursor hovers the image, a vertical and an horizontal lines, are drawn at the cursor position. Next to the cursor position, I have a box displaying some data (i.e. rgba pixel values).

    To manage most parts of these requirements, I subclassed QGraphicsView and also custom QGraphicsScene.

    My subclassed view manages the zoom by overriding wheelEvent(QWheelEvent* event).

    My subclassed scene contains the scene items and manages the mouse events when hovering. The member lines, box and text ignore the scaling.

    @
    m_pRectInfo_O->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
    @

    Also note that the lines have a position offset of 0.5 pixel, to be aligned with the image pixel.

    @
    m_pHLine_O->setPos(0.5, y+0.5); // a line has no width so, +0.5 to paint the line on the pixel and not at the border of two pixels
    m_pVLine_O->setPos(x+0.5,0.5);
    @

    All is working quite well except that when I zoom in, some misalignment can occur between the vertical/horizontal lines and the image pixels (see the image below).

    I don't understand this behavior as all the positions specified are in the "scene" world, and the scale come from the view. What am I doing wrong ?

    Best regards,

    Julien

    !https://scontent-a-ams.xx.fbcdn.net/hphotos-ash3/555965_10152062159384903_178021155_n.jpg(image)!

    !https://scontent-a-ams.xx.fbcdn.net/hphotos-frc3/1457707_10152062159374903_55035940_n.jpg(misalignment)!

    1 Reply Last reply
    0
    • L Offline
      L Offline
      lugemononeurone
      wrote on last edited by
      #2

      My subclassed view code is

      ImageAnalyzisGraphicsView.h

      @

      #ifndef IMAGEANALYZISGRAPHICSVIEW_H
      #define IMAGEANALYZISGRAPHICSVIEW_H

      #include <QGraphicsView>
      #include <QGraphicsRectItem>
      #include "ImageAnalyzisGraphicsScene.h"

      class ImageAnalyzisGraphicsView : public QGraphicsView
      {
      public:
      ImageAnalyzisGraphicsView(QWidget* parent = NULL);

      ImageAnalyzisGraphicsScene* mScene_O;
      protected:

      //Take over the interaction
      virtual void wheelEvent(QWheelEvent* event);
      };

      #endif // IMAGEANALYZISGRAPHICSVIEW_H

      @

      ImageAnalyzisGraphicsView.cpp

      @

      #include "ImageAnalyzisGraphicsView.h"

      //Qt includes
      #include <QGraphicsScene>
      #include <QGraphicsTextItem>
      #include <QTextStream>
      #include <QScrollBar>
      #include <QMouseEvent>
      #include <QWheelEvent>
      #include <QDebug>

      /**

      • Sets up the subclassed QGraphicsView
        /
        ImageAnalyzisGraphicsView::ImageAnalyzisGraphicsView(QWidget
        parent) : QGraphicsView(parent) {

        setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing |QPainter::SmoothPixmapTransform);
        setAlignment(Qt::AlignLeft|Qt::AlignTop);

        //Set-up the scene
        mScene_O = new ImageAnalyzisGraphicsScene(this);
        setScene(mScene_O);

        //Use ScrollHand Drag Mode to enable Panning
        setDragMode(ScrollHandDrag);
        // Enable mouse event
        setMouseTracking(true);

        viewport()->setProperty("cursor", QVariant(QCursor(Qt::CrossCursor)));
        }

      /**

      • Zoom the view in and out.
        /
        void ImageAnalyzisGraphicsView::wheelEvent(QWheelEvent
        event) {

        setTransformationAnchor(QGraphicsView::AnchorUnderMouse);

        // Scale the view / do the zoom
        double scaleFactor = 1.15;
        if(event->delta() > 0) {
        // Zoom in
        scale(scaleFactor, scaleFactor); //scale all the scene : some QGraphicsItem can ignore the scale transformation by setFlag(QGraphicsItem::ItemIgnoresTransformations, true);

        } else {
        // Zooming out
        scale(1.0 / scaleFactor, 1.0 / scaleFactor); //scale all the scene
        }

        // Don't call superclass handler here
        // as wheel is normally used for moving scrollbars
        }

      @

      1 Reply Last reply
      0
      • L Offline
        L Offline
        lugemononeurone
        wrote on last edited by
        #3

        My subclassed scene is

        ImageAnalyzisGraphicsScene.h

        @

        #ifndef IMAGEANALYZISGRAPHICSSCENE_H
        #define IMAGEANALYZISGRAPHICSSCENE_H

        #include <QGraphicsScene>
        #include <QGraphicsLineItem>
        #include <QGraphicsRectItem>
        #include <QGraphicsTextItem>
        #include <QGraphicsSimpleTextItem>
        #include <QPainter>
        #include <QEvent>
        #include <QHoverEvent>
        #include <QDebug>
        #include <QGraphicsSceneMouseEvent>
        #include <QCursor>

        class ImageAnalyzisGraphicsScene : public QGraphicsScene
        {
        Q_OBJECT

        public:
        ImageAnalyzisGraphicsScene(QObject * parent = 0);

        public:
        void LoadMyImage(QString myImg_Str);

        protected:

        virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent);
        //virtual void mousePressEvent(QMouseEvent * event)
        //virtual void mouseReleaseEvent(QMouseEvent * event)

        private:

        bool mInitialized_B;

        public:
        QGraphicsRectItem *m_pRectInfo_O;
        QGraphicsTextItem *m_pPixelInfo_O;

        QGraphicsLineItem *m_pVLine_O;
        QGraphicsLineItem *m_pHLine_O;

        QGraphicsPixmapItem * m_pGraphPixmap_O;

        };

        #endif // IMAGEANALYZISGRAPHICSSCENE_H

        @

        1 Reply Last reply
        0
        • L Offline
          L Offline
          lugemononeurone
          wrote on last edited by
          #4

          ImageAnalyzisGraphicsScene.cpp

          @
          #include "ImageAnalyzisGraphicsView.h"

          ImageAnalyzisGraphicsScene::ImageAnalyzisGraphicsScene( QObject * parent /= 0/ ):QGraphicsScene(parent)
          {
          mInitialized_B=false;
          setBackgroundBrush( Qt::black );
          setSceneRect(QRectF(0,0, 200,200)); //forcing the size of the scene
          }

          void ImageAnalyzisGraphicsScene::LoadMyImage( QString myImg_Str )
          {
          if(!mInitialized_B)
          {
          /*
          Create the QGraphicsItems
          */
          QPixmap Pixmap_O;
          m_pGraphPixmap_O =addPixmap(Pixmap_O);

            m_pRectInfo_O = addRect(QRectF(0, 0,150,30),QPen(Qt::black), QBrush(Qt::black));//, QBrush(Qt::black));//QPen(Qt::black),
            m_pRectInfo_O->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
            m_pPixelInfo_O = addText("POS(255,255)\nRGBA(255,255,255,255)");  // Initialized with the max text size
            m_pPixelInfo_O->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
            m_pPixelInfo_O->setDefaultTextColor(QColor(Qt::white));
            m_pPixelInfo_O->setHtml(QString("<div >") + "" + "</div>"); // n'a pas d'effet
          
            m_pHLine_O= addLine(QLine(0,0,width(),0),  QPen(Qt::white));
            m_pVLine_O= addLine(QLine(0,0,0,height()),  QPen(Qt::white));   
          
            /*
               lines opacity management : don't work
            */
            double tmp =m_pHLine_O->effectiveOpacity() ;
            //m_pHLine_O->setFlag ( QGraphicsItem::ItemIgnoresParentOpacity); // ne semble pas fonctionner
            m_pHLine_O->setOpacity(0.25);
            m_pVLine_O->setOpacity(0.25);
            tmp =m_pHLine_O->effectiveOpacity() ;
          

          }

          QPixmap Pixmap_O;
          Pixmap_O.load(myImg_Str);
          m_pGraphPixmap_O->setPixmap(Pixmap_O);
          setSceneRect(m_pGraphPixmap_O->boundingRect()); //forcing the size of the scene with the image size

          //resize the lines
          m_pHLine_O->setLine(0,0,width(),0);
          m_pVLine_O->setLine(0,0,0,height());
          m_pHLine_O->setPos(0, 0);
          m_pVLine_O->setPos(0, 0);

          m_pPixelInfo_O->setPos(0,0);
          m_pGraphPixmap_O->setPos(0,0);

          mInitialized_B=true;
          }

          void ImageAnalyzisGraphicsScene::mouseMoveEvent( QGraphicsSceneMouseEvent * mouseEvent )
          {
          if(mInitialized_B)
          {
          int InfoSizeUnitMargin_i=15;
          int InfoPosUnitMargin_i=1;

            //get the cursor position in the scene
            int x = mouseEvent->scenePos().x();
            int y = mouseEvent->scenePos().y();
          
          
            //check if position is in the scene rectangle : todo
            //if(m_pGraphPixmap_O->contains(mouseEvent->scenePos()))   // tient compte de l'alpha value
            //if(sceneRect().contains(mouseEvent->scenePos()))   
            QRectF rectTemp = m_pGraphPixmap_O->boundingRect();
            QPointF pointftemp=mouseEvent->scenePos();
          
             //Returns true if the point (x, y) is inside or on the edge of the rectangle; otherwise returns false. ==> 
            if((x>=0)&&(y>=0)&&(x<=width()-1)&&(y<=height()-1))  
            {
               m_pGraphPixmap_O->setPos(0,0);
          
               //set the lines positions 
               m_pHLine_O->setPos(0.5, y+0.5); // a line has no width so, +0.5 to paint the line on the pixel and not at the border of two pixels
               m_pVLine_O->setPos(x+0.5,0.5);
               
               //pixel access is done with QImage
               QImage Img = m_pGraphPixmap_O->pixmap().toImage();
               QRgb RgbPix=Img.pixel(x,y);
          
               int a=qAlpha(RgbPix);
               int r=qRed(RgbPix);
               int g=qGreen(RgbPix);
               int b=qBlue(RgbPix);
          
               /*
                  Set the text position.
                  Be careful to print the text only inside the existing scene size. 
                  Otherwise, the scene size will augment.
               */
               m_pPixelInfo_O->setPlainText(QString("POS(%1,%2)\nRGBA(%3,%4,%5,%6)").arg(x).arg(y).arg(r).arg(g).arg(b).arg(a));  
               //m_pRectInfo_O = addRect(QRectF(0, 0, m_pPixlInfo_O->boundingRect().width()+InfoSizeUnitMargin_i, m_pPixlInfo_O->boundingRect().height()+2),QPen(Qt::black), QBrush(Qt::black));
          
               qDebug()<< QString(" m_pPixlInfo_O (%1, %2)").arg(m_pPixelInfo_O->boundingRect().width()).arg(m_pPixelInfo_O->boundingRect().height());
          
               bool InfoAtCursorRight_B=(x+m_pPixelInfo_O->boundingRect().width()+InfoPosUnitMargin_i+InfoSizeUnitMargin_i <width())?true:false;
               bool InfoAtCursorBottom_B=(y+m_pPixelInfo_O->boundingRect().height()+InfoPosUnitMargin_i+InfoSizeUnitMargin_i <height())?true:false;
          
               if(InfoAtCursorRight_B && InfoAtCursorBottom_B)
               {
                  m_pPixelInfo_O->setPos(x+InfoPosUnitMargin_i,y+InfoPosUnitMargin_i);
               }
               else if(!InfoAtCursorRight_B && InfoAtCursorBottom_B)
               {
                  m_pPixelInfo_O->setPos(x-m_pPixelInfo_O->boundingRect().width()-(InfoPosUnitMargin_i+InfoSizeUnitMargin_i),y+InfoPosUnitMargin_i);
               }
               else if(InfoAtCursorRight_B && !InfoAtCursorBottom_B)
               {
                  m_pPixelInfo_O->setPos(x+InfoPosUnitMargin_i,y-m_pPixelInfo_O->boundingRect().height()-InfoPosUnitMargin_i);
               }
               else
               {
                  m_pPixelInfo_O->setPos(x-m_pPixelInfo_O->boundingRect().width()-(InfoPosUnitMargin_i+InfoSizeUnitMargin_i),y-m_pPixelInfo_O->boundingRect().height()-InfoPosUnitMargin_i);
               }
          
               m_pRectInfo_O->setPos(m_pPixelInfo_O->x(), m_pPixelInfo_O->y());
          
               qDebug()<< QString(" (%1, %2) :r %3 g %4 b %5 a %6").arg(x).arg(y).arg(r).arg(g).arg(b).arg(a);
          
               // the image update s  not perfect : there is a problem with lines drawing
               //QPixmap Pixmap_O=m_pGraphPixmap_O->pixmap();
               //m_pGraphPixmap_O->update();//otherwise, there is a problem with lines drawing
          
               update(); // otherwise, there are some strange behaviors in the painting
          
            }
            else
            {
          
            }
          

          }

          }

          @

          1 Reply Last reply
          0
          • L Offline
            L Offline
            lugemononeurone
            wrote on last edited by
            #5

            Mistake : lines do not ignore the transformation.

            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