文章学习自:
Qt_绘图框架_QGraphicsview实现缩放移动图片_Livy0123的博客-CSDN博客
这里进行一些自己的分析和理解。
(1)
自定义类MyGraphicsView继承自QGraphicsView
核心是重定义的滚轮事件。
void MyGraphicsView::wheelEvent(QWheelEvent *ev)
{
    if(Qt::CTRL == ev->modifiers())   //键盘CTRL键
    {
        if(ev->delta() > 0)
        {
            qrTmp = 1.2;
            this->scale(qrTmp,qrTmp);
        }
        else
        {
            qrTmp = 1.0/1.2;
            this->scale(qrTmp,qrTmp);
        }
        m_qrScaledNum *= qrTmp;  //保存放大倍数
    }
}实现功能是:通过转动滚轮,放大或缩小view,进而形成这样的视觉效果。
 
相关知识:
ev->modifiers();
返回可能伴随wheel事件的键盘修饰符。
Constant
Value
Qt3DInput::QWheelEvent::NoModifier
Qt::NoModifier
Qt3DInput::QWheelEvent::ShiftModifier
Qt::ShiftModifier
Qt3DInput::QWheelEvent::ControlModifier
Qt::ControlModifier
Qt3DInput::QWheelEvent::AltModifier
Qt::AltModifier
Qt3DInput::QWheelEvent::MetaModifier
Qt::MetaModifier
Qt3DInput::QWheelEvent::KeypadModifier
Qt::KeypadModifier
    enum Modifier {
        META          = Qt::MetaModifier,
        SHIFT         = Qt::ShiftModifier,
        CTRL          = Qt::ControlModifier,
        ALT           = Qt::AltModifier,
        MODIFIER_MASK = KeyboardModifierMask,
        UNICODE_ACCEL = 0x00000000
    };ev->delta();
每当滚轮转动一下,默认是15度
这时调用QWheelEvent()::delta()返回的值就是15*8=120。
ev->delta(); //滑动的距离 //向下滑动为负值 //向上滑动为正值
(2)
 
这个动图中,无法实现随着鼠标的移动,放大那个区域的图像。
而下面这个动图可以。
 
  
关键代码:
    this->setMouseTracking(true);   //跟踪鼠标位置
    //这两句的作用:
    //以鼠标中心点为锚点
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    setResizeAnchor(QGraphicsView::AnchorUnderMouse);(3)初始化MyGraphicsView对象和QGraphicsScene对象。
    //创建视图
    this->m_pView = new MyGraphicsView(this);
    m_pView->resize(VIEW_MAX_WIDTH,VIEW_MAX_HEIGHT);
    this->m_nViewWidth = m_pView->width();
    this->m_nViewHeight = m_pView->height();
    //创建场景
    this->m_pScene = new QGraphicsScene(this);
    //设置场景大小和左上角点坐标
    this->m_pScene->setSceneRect(0,0,VIEW_MAX_WIDTH,VIEW_MAX_HEIGHT);(4)创建QGraphicsPixmapItem对象存储图片。
     //加载图片
     QString strFilePath = QFileDialog::getOpenFileName(this,tr("Load a Image!"),"C:/Users/zhengfei6/Desktop/testImage",tr("Images(*.png *.jpg *.bmp)"));
     if(NULL == strFilePath)
     {
         cout << "FilePath is Null";
         return;
     }
     //加载图片
     QPixmap pix;
     pix.load(strFilePath);
     QGraphicsPixmapItem *pPixItem = new QGraphicsPixmapItem(pix);
     pPixItem->setFlag(QGraphicsItem::ItemIsMovable,true);//item可移动
(5)为了显示时直接适应视图,需要调整pPixItem的大小和位置。
     //获取缩放比例
     DisplayModeEnum displayMode = DisplayModeEnum::TOPLEFT;  //默认左上顶点显示
     this->m_qrDefaultShrinkedRatio = GetDefaultRatio(pix,displayMode);
     pPixItem->setScale(1/this->m_qrDefaultShrinkedRatio);//调整item大小,实际上,图像大小是没有变的。程序作用:
返回值 :图像的伸缩比例。
displayMode:
三种显示模式:
宽度>高度

高度>宽度

 pos=(0,0)
qreal MyWidget::GetDefaultRatio(const QPixmap &pix,DisplayModeEnum &displayMode)
{
    qreal dResRatio = 0;
    qreal qrWidthRatio = (qreal)pix.width()/(qreal)VIEW_MAX_WIDTH;
    qreal qrHeightRatio = (qreal)pix.height()/(qreal)VIEW_MAX_HEIGHT;
    cout << "qrWidthRatio = "<< qrWidthRatio;
    cout << "qrHeightRatio = "<< qrHeightRatio;
    qreal nMaxTmp = qMax(qrWidthRatio,qrHeightRatio);  //取宽宽比和高高比的大者
    //举例:pix(1080,600),view(1080,400)
    //1,1.5
    //为了成功放下这张图片,需要调整图片大小为(1080*2/3,600*2/3)
    //宽调整为一致,看高,如果pix更大,放弃
    //高调整为一致,看宽,如果pix更大,放弃
    //  cout << "nMaxTmp = "<< nMaxTmp;
    if(qrWidthRatio == nMaxTmp)//宽宽比>高高比
    {
        dResRatio = qrWidthRatio;
        displayMode = DisplayModeEnum::YVerticalMiddle;//Y垂直轴居中
    }
    else//宽高比<=高高比
    {
        dResRatio = qrHeightRatio;
        displayMode = DisplayModeEnum::XHorizontalMiddle;//X水平轴居中
    }
    //cout << "dResRatio = "<< dResRatio;
    return dResRatio;
}


















