QItems alignment problem when using scaling with custom graphicsView and graphicsScene



  • 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)!



  • 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
      }

    @



  • 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

    @



  • 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
      {
    
      }
    

    }

    }

    @



  • Mistake : lines do not ignore the transformation.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.