Qt 鼠标拖动缩放

来源:互联网 发布:中兴通讯知乎 编辑:程序博客网 时间:2024/06/05 21:06
在Qt drag和drop基础上,实现QGraphicsItem的鼠标拖动缩放,效果如下:



 
如图所示,整个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事件,什么多不做
 
以上是主要代码,完整源码:点击下载
原创粉丝点击