场景:当同时按下Ctrl键和滚动滑轮时,进行按当前鼠标为中心点缩放图片
Qt: QLabel+QPainter
实现原理:
前提假设图片加载到QLabel上时图片左上角位于QLabel的左上角。
注:没有考虑要更改QLabel的物理位置。
//.cpp代码块:
bool ImageScaleTest::eventFilter(QObject* o, QEvent* e) {
if(this->pImageLabel)
if (o== this->pImageLabel){
if( e->type() == QEvent::Wheel) {
QWheelEvent* event = static_cast<QWheelEvent*>(e);
if (event->modifiers() & Qt::ControlModifier) { //触发缩放事件
int radius = event->angleDelta().y();
qreal scale = 1.05;
if (radius < 0)
scale = 1 / 1.05;
if (this->pos != event->pos()) //当前鼠标缩放点与上一次鼠标缩放点不同 ⑴
this->imageLT = (this->posToImageLT * this->pd - (event->pos()-this-
>pos)) * (1 / this->pd) + event->pos();
this->pd *= scale; //本次缩放操作时对应的图片的缩放比
this->pos = event->pos();
this->pImageLabel->repaint(); //进行绘制
return true;
}
return true;
}
else if (e->type() == QEvent::Paint) {
QPaintEvent* event = static_cast<QPaintEvent*>(e);
QPainter painter(this->pImageLabel);
painter.translate(this->pos); //平移缩放原点到当前鼠标位置
this->posToImageLT = (this->imageLT - this->pos); //图片左上角相对于鼠标的坐标
painter.scale(this->pd, this->pd); //进行坐标系缩放
painter.drawPixmap(posToImageLT, QPixmap::fromImage(this->image));
return true;
}
}
if (o == ui.scrollArea->viewport()) {
if (e->type() == QEvent::Wheel) { //过滤掉QScrollArea->viewport的缩放事件
QWheelEvent* event = static_cast<QWheelEvent*>(e);
if (event->modifiers() & Qt::ControlModifier) {
e->ignore();
return true;
}
return false;
}
else
return false;
}
return false;
}
void ImageScaleTest::pushButton_cameraClicked() { //按钮点击时加载图片并设置当前图片的相关坐标位置
QImage image(":/ImageScaleTest/testImage.jpg");
this->image = image;
if(!this->pImageLabel){
this->pImageLabel = new QLabel;
this->pImageLabel->installEventFilter(this);
ui.scrollArea->setWidget(this->pImageLabel); //设置QLabel为场景
ui.scrollArea->setWidgetResizable(true);
}
this->pImageLabel->setPixmap(QPixmap::fromImage(image));
this->pImageLabel->setScaledContents(true);
this->pd = 1;
this->pos=QPoint(0, 0);
this->imageLT= QPoint(0, 0);
}
// .h代码块:
protected:
void initWidget();
virtual bool eventFilter(QObject* o, QEvent* e) override;
private:
qreal pd = 1;
QImage image;
QPoint pos; //缩放因子
QPoint imageLT; //当前缩放点对应的原始图片左上角的坐标
QPoint posToImageLT; //图片左上角相对于鼠标为原点的坐标
QLabel* pImageLabel = nullptr;
原理(1):
通过向量运算确定图片相关的坐标位置。对于同一个缩放点每次缩放对原始图片进行缩放,当鼠标位置改变时对应的缩放点要重新计算图片相对于QLabel左上角为原点的坐标。
本文为工作学习总结,若有错误地方恳请指正