文章学习自:
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;
}