QGraphicsView图像显示、缩放、拖拽记录

工程源文件

码云地址

演示动图

动画演示

参考文章

  1. View、Scene、Item坐标系关系
  2. 重写QGraphicsItem

主要解决问题

  1. 自定义QGraphicsView类,简化外界设置图片步骤。
  2. 理清三种坐标系关系。

主要代码

.h

class MyGraphicsView : public QGraphicsView
{
    Q_OBJECT
public:
    MyGraphicsView(QWidget *parent = nullptr);
    ~MyGraphicsView();
    void setPixmap(const QPixmap *pixmap);	//外界配置图片方法
    void resetPixmap();						//重置图片方法
protected:
    virtual void mousePressEvent(QMouseEvent *event);	//鼠标按下事件,拖拽动作开始
    virtual void mouseReleaseEvent(QMouseEvent *event);	//鼠标松开事件,拖拽动作结束
    virtual void mouseMoveEvent(QMouseEvent *event);	//鼠标移动事件,拖拽动作实现
    virtual void wheelEvent(QWheelEvent *event);		//图片缩放实现
private:
    QGraphicsScene*         m_scene = nullptr;			//私有场景
    QGraphicsPixmapItem*    m_imageItem = nullptr;		//私有图片图元
    QPixmap                 m_pixmap;					//备份图片数据
    QPointF                 m_mousePos;					//记录鼠标按下时开始位置
    bool                    m_dragFlag;					//记录是否执行拖拽
    qreal                   m_curScaleValue;			//记录当前缩放比例
    qreal                   m_defaultScaleValue;		//记录原始缩放比例
};

.cpp

#define SCALE_MAX       50		//最大放大比例
#define ZOOMUP_VALUE    1.1		//单次放大比例
#define ZOOMDOWN_VALUE  0.9		//单次缩小比例

MyGraphicsView::MyGraphicsView(QWidget *parent) : QGraphicsView(parent),
    m_curScaleValue(1),
    m_defaultScaleValue(1)
{
    m_scene = new QGraphicsScene(this);
    this->setScene(m_scene);	//配置场景
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);	//禁用显示滚动条
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);	//禁用显示滚动条
}

MyGraphicsView::~MyGraphicsView()
{

}

void MyGraphicsView::setPixmap(const QPixmap *pixmap)
{
    if(m_scene->items().size())	//若当前场景中已有图片,则先清空,还原视图
    {
        m_scene->clear();
        QMatrix q;
        q.setMatrix(1, this->matrix().m12(),
                    this->matrix().m21(), 1,
                    this->matrix().dx(),
                    this->matrix().dy());
        this->setMatrix(q,false);
    }
    m_pixmap = *pixmap;	//记录图片数据
    m_defaultScaleValue = qMin(this->width() * 1.0 / m_pixmap.width(),
                             this->height() * 1.0 / m_pixmap.height());	//计算初始缩放比例
    m_imageItem = m_scene->addPixmap(m_pixmap);	//添加图元
    resetPixmap();	//重置图片
    this->setSceneRect(0, 0, this->width(), this->height());	//设置视图大小
    update();
}

void MyGraphicsView::resetPixmap()
{
    m_curScaleValue = m_defaultScaleValue;	//还原当前缩放比例为初始缩放比例
    m_imageItem->setScale(m_defaultScaleValue);	//还原图元缩放比例
    m_imageItem->setPos(0,0);	//设置图元位置
    //将图元至于视图中心
    m_imageItem->moveBy((this->width()  - m_pixmap.width()  * m_defaultScaleValue) / 2.0,
                        (this->height() - m_pixmap.height() * m_defaultScaleValue) / 2.0);
}


void MyGraphicsView::mousePressEvent(QMouseEvent *event)
{
    if(m_imageItem == nullptr)
        return;
    if(event->button()== Qt::LeftButton)
    {
    	//鼠标左键按下,开始拖拽
        m_mousePos = m_imageItem->mapFromScene(this->mapToScene(event->pos()));
        m_dragFlag = true;
    }
    else if(event->button() == Qt::RightButton)
    {
    	//鼠标右键按下,还原图元
        resetPixmap();
    }
}

void MyGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
    Q_UNUSED(event)
    m_dragFlag = false;	//鼠标松开,拖拽结束
}

void MyGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
    if(m_dragFlag)
    {
    	//执行拖拽动作
        QPointF point = (m_imageItem->mapFromScene(this->mapToScene(event->pos()))
                         - m_mousePos)*m_curScaleValue;	//计算拖拽距离
        //执行拖拽动作,相当于执行m_imageItem->setPos(pos() + QPointF(dx, dy));
        m_imageItem->moveBy(point.x(), point.y());
    }
}

void MyGraphicsView::wheelEvent(QWheelEvent *event)
{
    if(m_imageItem == nullptr)
        return;
	//执行缩放动作
    if((event->delta() > 0)&&(m_curScaleValue >= SCALE_MAX))
    {
        return;	//当前图元放大已达到最大比例,忽略。
    }
    else if((event->delta() < 0)&&(m_curScaleValue <= m_defaultScaleValue))
    {
        resetPixmap();	//当前图元已缩小至初始比例,还原图元。
    }
    else
    {
    	//更新当前缩放比例
        m_curScaleValue*= event->delta() > 0 ? ZOOMUP_VALUE : ZOOMDOWN_VALUE;
        //缩放图元
        m_imageItem->setScale(m_curScaleValue);
        //计算当前鼠标在图元坐标系内的位置
        QPointF pos = m_imageItem->mapFromScene((this->mapToScene(event->pos())));
        //计算图元应移动多少距离才能够将鼠标置于未缩放之前位置
        pos *= event->delta() > 0 ? -0.1 * m_curScaleValue : 0.1 * m_curScaleValue;
        //移动图元
        m_imageItem->moveBy(pos.x(), pos.y());
    }
}

使用方法

void MainWindow::on_pushButton_clicked()
{
    QPixmap image("./testpcbout.bmp");
    ui->graphicsView->setPixmap(&image);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值