工程源文件
演示动图
参考文章
主要解决问题
- 自定义QGraphicsView类,简化外界设置图片步骤。
- 理清三种坐标系关系。
主要代码
.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);
}