#include <QGraphicsItem>class MyItem : public QGraphicsItem{public: enum PointType { None, ResizeLeftTop, ResizeTop, ResizeRightTop, ResizeLeft, ResizeRight, ResizeLeftBottom, ResizeBottom, ResizeRightBottom, Rotate, Move }; MyItem( QGraphicsItem* parent = 0 ); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);private: PointType pointTypeAtPos( const QPointF &pos ) const; void setCursorShape( const QPointF &pos ); qreal w,h; PointType pointType; QPointF startItemPoint; QPointF startMousePoint; qreal kx,ky,alpha; qreal kx0,ky0,alpha0; QTransform transform, transform_inv;protected: void mousePressEvent( QGraphicsSceneMouseEvent *event ); void mouseMoveEvent ( QGraphicsSceneMouseEvent *event ); void hoverMoveEvent ( QGraphicsSceneHoverEvent *event );};
#include <QtGui>#include "item.h"MyItem::MyItem( QGraphicsItem * parent ) : QGraphicsItem( parent ){ setFlags( QGraphicsItem::ItemIsSelectable ); w = 50; h = 50; pointType = None; kx=ky=1.0; alpha=0.0; setAcceptHoverEvents ( true ); }QRectF MyItem::boundingRect() const{ const qreal border = 5; return QRectF( -w/2-border, -h/2-border, w+2*border, h+2*border );}void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ Q_UNUSED(option); Q_UNUSED(widget); painter->drawRect( -w/2, -h/2, w, h );}void MyItem::mousePressEvent( QGraphicsSceneMouseEvent *event ){ QGraphicsItem::mousePressEvent( event ); if( !isSelected() ) return; if(event->button() == Qt::LeftButton) { startMousePoint = event->scenePos(); startItemPoint = scenePos(); pointType = pointTypeAtPos( event->pos() ); setCursorShape( event->pos() ); kx0 = kx; ky0 = ky; alpha0 = alpha; QPointF p0; switch( pointType ) { case( ResizeLeftTop ): p0 = QPointF( w/2, h/2 ); break; case( ResizeTop ): p0 = QPointF( 0, h/2 ); break; case( ResizeRightTop ): p0 = QPointF( -w/2, h/2 ); break; case( ResizeLeft ): p0 = QPointF( w/2, 0 ); break; case( ResizeRight ): p0 = QPointF( -w/2, 0 ); break; case( ResizeLeftBottom ): p0 = QPointF( w/2, -h/2 ); break; case( ResizeBottom ): p0 = QPointF( 0, -h/2 ); break; case( ResizeRightBottom ): p0 = QPointF( -w/2, -h/2 ); break; default:; } p0 = mapToScene( p0 ); transform.reset(); transform.rotateRadians( -alpha0 ); transform.translate( -p0.x(), -p0.y() ); transform_inv = transform.inverted(); }}void MyItem::mouseMoveEvent( QGraphicsSceneMouseEvent *event ){ QGraphicsItem::mouseMoveEvent( event ); if( !isSelected() ) return; if( pointType == None ) return; if( pointType == Move ) { QPointF p = startItemPoint + event->scenePos() - startMousePoint; setPos( mapToParent( mapFromScene( p ) ) ); return; } if( pointType != Rotate ) { QPointF pm = transform.map( startMousePoint ); QPointF pi = transform.map( startItemPoint ); QPointF pp = transform.map( event->scenePos() ); qreal kxx = pp.x() / pm.x(); qreal kyy = pp.y() / pm.y(); switch( pointType ) { case( ResizeTop ): case( ResizeBottom ): kxx = 1; break; case( ResizeLeft ): case( ResizeRight ): kyy = 1; break; default:; } kx = kx0 * kxx; ky = ky0 * kyy; qreal xx = pi.x() * kxx; qreal yy = pi.y() * kyy; QTransform tr; tr.rotateRadians( alpha0 ); tr.scale( kx,ky ); setTransform( tr ); setPos( mapToParent( mapFromScene( transform_inv.map( QPointF(xx,yy) ) ) ) ); return; } if( pointType == Rotate ) { QPointF p1 = transform.map( startMousePoint ); QPointF p2 = transform.map( event->scenePos() ); alpha = alpha0 + atan2( p2.y(), p2.x() ) - atan2( p1.y(), p1.x() ); QTransform tr; tr.rotateRadians( alpha ); tr.scale( kx,ky ); setTransform( tr ); return; }}void MyItem::hoverMoveEvent ( QGraphicsSceneHoverEvent * event ){ if(isSelected()) { setCursorShape( event->pos() ); } else { setCursor(Qt::ArrowCursor); }}void MyItem::setCursorShape( const QPointF &pos ){ switch( pointTypeAtPos( pos ) ) { case( ResizeLeftTop ): setCursor(Qt::SizeFDiagCursor); break; case( ResizeTop ): setCursor(Qt::SizeVerCursor); break; case( ResizeRightTop ): setCursor(Qt::SizeBDiagCursor); break; case( ResizeLeft ): setCursor(Qt::SizeHorCursor); break; case( ResizeRight ): setCursor(Qt::SizeHorCursor); break; case( ResizeLeftBottom ): setCursor(Qt::SizeBDiagCursor); break; case( ResizeBottom ): setCursor(Qt::SizeVerCursor); break; case( ResizeRightBottom ): setCursor(Qt::SizeFDiagCursor); break; case( Rotate ): setCursor(Qt::SizeAllCursor); break; case( Move ): setCursor(Qt::OpenHandCursor); break; default: setCursor(Qt::ArrowCursor); }}inline static qreal norm( qreal x, qreal y ){ return sqrt( x*x + y*y );}MyItem::PointType MyItem::pointTypeAtPos( const QPointF &pos ) const{ qreal x = pos.x(); qreal y = pos.y(); qreal dx = w/50; qreal dy = h/50; qreal dxy = qMax( dx,dy ); if( norm( -w/2-x, -h/2-y ) < dxy ) return ResizeLeftTop; if( norm( w/2-x, -h/2-y ) < dxy ) return ResizeRightTop; if( norm( -w/2-x, h/2-y ) < dxy ) return ResizeLeftBottom; if( norm( w/2-x, h/2-y ) < dxy ) return ResizeRightBottom; if( fabs( -w/2-x ) < dx ) return ResizeLeft; if( fabs( w/2-x ) < dx ) return ResizeRight; if( fabs( -h/2-y ) < dy ) return ResizeTop; if( fabs( h/2-y ) < dy ) return ResizeBottom; if( fabs( -w/2-x+2*dx ) < dx ) return Rotate; if( fabs( w/2-x-2*dx ) < dx ) return Rotate; if( fabs( -h/2-y+2*dy ) < dy ) return Rotate; if( fabs( h/2-y-2*dy ) < dy ) return Rotate; return Move;}