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
Forum Updated to NodeBB v4.3 + New Features

QItems alignment problem when using scaling with custom graphicsView and graphicsScene

Scheduled Pinned Locked Moved General and Desktop
5 Posts 1 Posters 2.4k 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