Qt实现按鼠标为中心的图片缩放

场景:当同时按下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左上角为原点的坐标。

                                                                                   本文为工作学习总结,若有错误地方恳请指正

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值