#ifndef PICTUREVIEWINGCONTROL_H
#define PICTUREVIEWINGCONTROL_H
#include <QWidget>
class PictureViewingControl : public QWidget
{
Q_OBJECT
public:
PictureViewingControl(QWidget * parent = nullptr);
~PictureViewingControl();
void setPixmap(const QString &imgFilePath);
private:
void paintEvent(QPaintEvent *event)override;
bool event(QEvent * event)override;
public:
enum class ActionType
{
Amplification,//放大
Shrink,//缩小
Move,//移动
None//不进行任何操作
};
private:
QPoint Alloffset;//总偏移
QPoint offset;
QRect paintRect;
QRect drawRect;
QPixmap img_src;//源图
ActionType action;//操作
double ratio;//缩放比例
};
#endif // PICTUREVIEWINGCONTROL_H
#include "pictureviewingcontrol.h"
#include <QWheelEvent>
#include <QPainter>
PictureViewingControl::PictureViewingControl(QWidget *parent):
QWidget(parent)
{
action = ActionType::None;//初始动作:什么都不做
ratio = 1.0;
Alloffset = QPoint(0,0);
}
PictureViewingControl::~PictureViewingControl()
{
}
bool PictureViewingControl::event(QEvent * event)
{
static bool press = false;//是否按下了左键
static QPoint PreDot;
auto type = event->type();
if(type == QEvent::MouseButtonPress )//鼠标按下事件
{
if(QMouseEvent *mouse = static_cast<QMouseEvent* >(event))
{
if(mouse->button() == Qt::LeftButton && drawRect.contains(mouse->pos()))
{
press = true;
PreDot = mouse->pos();
setCursor(QCursor(Qt::ClosedHandCursor));
}
}
}
else if(type == QEvent::MouseButtonRelease)//鼠标松开事件
{
if(QMouseEvent *mouse = static_cast<QMouseEvent* >(event))
{
if(mouse->button() == Qt::LeftButton && press)
{
press = false;
}
setCursor(QCursor(Qt::OpenHandCursor));
}
}
else if(type == QEvent::MouseMove)//移动鼠标
{
if(press)
{
if(QMouseEvent *mouse = static_cast<QMouseEvent* >(event))
{
offset.setX(mouse->x() - PreDot.x());
offset.setY(mouse->y() - PreDot.y());
PreDot = mouse->pos();
action = ActionType::Move;
this->repaint();
}
}
}
else if(type == QEvent::Wheel)
{
if(QWheelEvent *mouse = static_cast<QWheelEvent* >(event))
{
if(mouse->angleDelta().y() < 0)
{
//下滑,缩小
action = ActionType::Shrink;
this->repaint();
action = ActionType::None;
}
else
{
//上滑,放大
action = ActionType::Amplification;
this->repaint();
action = ActionType::None;
}
}
}
return QWidget::event(event);
}
void PictureViewingControl::setPixmap(const QString & imgFilePath)
{
img_src.load(imgFilePath);
ratio = 0.2;
Alloffset = QPoint(0,0);
offset = QPoint(0,0);
repaint();
}
void PictureViewingControl::paintEvent(QPaintEvent *event)
{
if(img_src.isNull())
{
return;
}
auto rect = event->rect();
paintRect = QRect(1, 1, rect.width() + 1, rect.height() + 1);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);//开启抗锯齿
int NowW = ratio * img_src.width();//缩放后的图片尺寸
int NowH = ratio * img_src.height();
if(action == ActionType::Shrink)//缩小
{
ratio -= 0.1 * ratio;
if(ratio < 0.2)
{
ratio = 0.2;
}
}
if(action == ActionType::Amplification)//放大
{
ratio += 0.1 * ratio;
if(ratio > 2)
{
ratio = 2;
}
}
auto temp_img = img_src.copy().scaled(NowW, NowH,Qt::KeepAspectRatio);
if(action == ActionType::Move)//移动
{
Alloffset.setX(Alloffset.x() + offset.x());
Alloffset.setY(Alloffset.y() + offset.y());
}
//限制偏移量 效果是图像超出边框太多则弹回来
if(abs(Alloffset.x()) >= (paintRect.width()/2 + NowW/2 - 10)) //限制X偏移值
{
if(Alloffset.x() > 0)
{
Alloffset.setX(paintRect.width()/2 + NowW/2 - 100);//右
}
else
{
Alloffset.setX(-paintRect.width()/2 + -NowW/2 + 100);//左
}
}
if(abs(Alloffset.y()) >= (paintRect.height()/2 + NowH/2 - 10)) //限制Y偏移值
{
if(Alloffset.y() > 0)
{
Alloffset.setY(paintRect.height()/2 + NowH/2 - 100);//下
}
else
{
Alloffset.setY(-paintRect.height()/2 + -NowH/2 + 100);//上
}
}
int x = paintRect.width()/2 + Alloffset.x() - NowW/2;
if(x < 0)
{
x = 0;
}
int y = paintRect.height()/2 + Alloffset.y() - NowH/2;
if(y < 0)
{
y = 0;
}
int sx = NowW/2 - paintRect.width()/2 - Alloffset.x();
if(sx < 0)
{
sx = 0;
}
int sy = NowH/2 - paintRect.height()/2 - Alloffset.y();
if(sy < 0)
{
sy = 0;
}
int w = (NowW - sx) > paintRect.width() ? paintRect.width(): (NowW - sx);
if(w > (paintRect.width() - x))
{
w = paintRect.width() - x;
}
int h = (NowH - sy) > paintRect.height() ? paintRect.height() : (NowH - sy);
if(h > (paintRect.height() - y))
{
h = paintRect.height() - y;
}
drawRect = QRect(x + paintRect.x(), y + paintRect.y(), w, h);
painter.drawTiledPixmap(drawRect,temp_img,QPoint(sx, sy)); //绘画图片
}
效果:
#include "pictureviewingcontrol.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PictureViewingControl w;
w.setPixmap(":/backgroundImage1.jpg");
w.show();
return a.exec();
}