Название: изменение размера фигур
Отправлено: serega-5508 от Апрель 02, 2011, 23:41
Вопрос такой, я рисую на прямоугольник на QGraphicsScene. Могу его перемещать по сцене (QGraphicsView). А вот как мне сделать так, чтобы я мог изменять размер этого прямоугольника, когда подвозу курсор к углу прямоугольника???
Название: Re: изменение размера фигур
Отправлено: madRoger от Апрель 03, 2011, 01:52
Я наследовался от QGraphicsItem. Переопределял mousePressEvent, mouseMoveEvent. Отслеживал нажатие клавиши мыши и перемещение при нажатой клавише. Далее рассчитывал изменение координат и строил матрицу трансформации. Для изменения размеров самого итема использовал QGraphicsItem::setTransform. Можно также использовать QGraphicsItem::setScale.
Название: Re: изменение размера фигур
Отправлено: serega-5508 от Апрель 05, 2011, 23:29
madRoger, можете представить свой код или скинуть посмотреть прогу?
у кого-нибудь есть ещё варианты и хоть часть кода?
Название: Re: изменение размера фигур
Отправлено: madRoger от Апрель 06, 2011, 00:10
.h #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 ); };
.cpp #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; }
Реализация немного специфична т.к. писал под конкретную задачу. Но суть та же. Еще есть поддержка вращения.
Название: Re: изменение размера фигур
Отправлено: serega-5508 от Апрель 06, 2011, 00:41
madRoger, спасибо. посмотрю, если возникнут вопросы, обращусь!
|