Qt 鼠标拖动缩放

在Qt drag和drop基础上,实现QGraphicsItem的鼠标拖动缩放,效果如下:
Qt 鼠标拖动缩放_第1张图片 Qt 鼠标拖动缩放_第2张图片


Qt 鼠标拖动缩放_第3张图片 
如图所示,整个item由两个QGraphicsItem组成,item1用来显示主图片,item2用来显示移动光标。
先来看item2的实现,它实现的功能有显示和消失(鼠标移动到item周围显示,其他地方消失)、颜色改变(使用鼠标缩放时改变颜色)。
void CornerGrabber : : paint ( QPainter * painter ,
const QStyleOptionGraphicsItem * ,
QWidget * )
{
// fill the box with solid color, use sharp corners
_outterborderPen . setCapStyle ( Qt : : SquareCap );
_outterborderPen . setStyle ( Qt : : SolidLine );
painter - > setPen ( _outterborderPen );
 
 
QPointF topLeft ( 0 , 0 );
QPointF bottomRight ( _width , _height );
 
 
QRectF rect ( topLeft , bottomRight );
 
 
QBrush brush ( Qt : : SolidPattern );
brush . setColor ( _outterborderColor );
painter - > fillRect ( rect , brush );
}
 
item2其实是一个巨型,宽和高由_width和_height确定,颜色由_outterborderColor确定,初始时黑色。
void CornerGrabber : :hoverLeaveEvent( QGraphicsSceneHoverEvent * )
{
    _outterborderColor = Qt : :black;
     this - >update( 0, 0,_width,_height);
}
 
void CornerGrabber : :hoverEnterEvent( QGraphicsSceneHoverEvent * )
{
    _outterborderColor = Qt : :red;
     this - >update( 0, 0,_width,_height);
}
当进入item2的hover事件时,将_outterborderColor设置为红色,然后重新绘制,离开时再该回黑色。
 
void CornerGrabber : :mouseMoveEvent(QGraphicsSceneDragDropEvent *event)
{
    event - >setAccepted( false);
}
 
void CornerGrabber : :mousePressEvent(QGraphicsSceneDragDropEvent *event)
{
    event - >setAccepted( false);
}
 
void CornerGrabber : :mouseReleaseEvent( QGraphicsSceneMouseEvent * event )
{
    event - >setAccepted( true);
}
 
void CornerGrabber : :mousePressEvent( QGraphicsSceneMouseEvent * event )
{
    event - >setAccepted( false);
}
 
void CornerGrabber : :mouseMoveEvent( QGraphicsSceneMouseEvent * event )
{
    event - >setAccepted( false);
}
以上代码,表示item2自己处理mouseReleaseEvent事件(实际什么也不做),其他四种事件不处理。
 
下面看一下item1的实现。
void WorkspaceItem : :paint(QPainter *painter,
                           const QStyleOptionGraphicsItem *option,
                          QWidget *widget)
{
    Q_UNUSED(option)
    Q_UNUSED(widget)
    painter - >drawPixmap(BoundDelta, BoundDelta, pixmap_);
     if(isSelected())
    {
        painter - >setPen(Qt : :DashLine);
        painter - >drawRect(BoundDelta, BoundDelta, pixmap_width, pixmap_height);
    }
}
先绘制中间显示的图片,如果被选中绘制虚线轮廓。
 
void WorkspaceItem : :hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    Q_UNUSED(event)
    corner = new CornerGrabber( this);
    corner - >installSceneEventFilter( this);
    updateCornerPosition();
}
 
void WorkspaceItem : :hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    Q_UNUSED(event)
     delete corner;
}
这里跟item2类似,但又一点注册事件过滤器,用来处理item2不处理的四种事件(处理方法见下面函数)。
 
bool WorkspaceItem : :sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
    CornerGrabber * corner = dynamic_cast <CornerGrabber * >(watched);
     if(corner == NULL)
         return false;
 
    QGraphicsSceneMouseEvent * mevent = dynamic_cast <QGraphicsSceneMouseEvent * >(event);
     if(mevent == NULL)
         return false;
 
     switch(event - >type())
    {
     case QEvent : :GraphicsSceneMousePress :
        corner - >setMouseState(CornerGrabber : :kMouseDown);
        corner - >mouseDownX = mevent - >pos().x();
        corner - >mouseDownY = mevent - >pos().y();
         break;
     case QEvent : :GraphicsSceneMouseRelease :
        corner - >setMouseState(CornerGrabber : :kMouseReleased);
         break;
     case QEvent : :GraphicsSceneMouseMove :
        corner - >setMouseState(CornerGrabber : :kMouseMoving );
         break;
     default :
         return false;
    }
 
     if(corner - >getMouseState() == CornerGrabber : :kMouseMoving)
    {
        qreal x = mevent - >pos().x(), y = mevent - >pos().y();
 
        qreal width = x - corner - >mouseDownX + pixmap_width;
        qreal height = y - corner - >mouseDownY + pixmap_height;
 
        QImage image;
         if(text == "Mark")
            image.load( ":/images/banner_mark.png");
         else
            image.load( ":/images/banner_text.png");
        QSize size = image.size();
         if(size.width() < pixmap_width || size.height() < pixmap_height)
        {
            width = size.width();
            height = size.height();
        }
        qreal xscale = width / size.width();
        qreal yscale = height / size.height();
 
        qreal scale = qMax(xscale,yscale);
 
        QMatrix matrix;
        matrix.scale(scale, scale);
        image = image.transformed(matrix);
        pixmap_ = QPixmap : :fromImage(image);
        pixmap_width = pixmap_.width();
        pixmap_height = pixmap_.height();
 
        updateCornerPosition();
        update();
        scene() - >update();
    }
     return true;
}
鼠标Press事件,记录鼠标位置
鼠标Move事件,如果数据左键是按下的,记录当前的位置,计算缩放后的大小和原先大小的比例,然后对图片按比例缩放
鼠标Release事件,什么多不做
 
以上是主要代码,完整源码:点击下载

你可能感兴趣的:(Qt)