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)!
-
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_OBJECTpublic:
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.