20.QT-Qpixmap实现图片鼠标缩放,鼠标拖动示例(详解)

通过 QPainter 绘画实现,以本地图片985*740为例

如下图所示:

效果如下所示:

 

 

实现原理

主要通过以下函数实现:

void QPainter::drawTiledPixmap ( int x, int y, int w int h const QPixmap & pixmap, int sx = 0, int sy = 0 );
      //平铺显示pixmap
      //x y w h :表示绘画区域
      //sx  sy  :表示Qpixmap绘画起始位置

 

只要算出x y w h sx sy就能实现超出窗口不显示的效果

举个例子,如下图所示,居中显示1200*1200时:

当图片左偏移600时,也就是offset=-600时,则只能在窗口上显示一半的图片:

 

代码实现

widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QtGui>

class Widget : public QWidget
{
    Q_OBJECT

private :
    QPixmap  *pix;
    int action;          //动作(放大,缩小,移动...)
    int pixW;            //图片宽
    int pixH;            //图片高

    QRect Paint;         //绘画区域

    float ratio;                //比例
    QPoint offset;              //一次的图片偏移值
    QPoint Alloffset;           //总偏移
    QLabel label;

    QPushButton  BigButton;
    QPushButton  LittleButton;
    QPushButton  LiftButton;
    QPushButton  RightButton;
    QPushButton  UpButton;
    QPushButton  DownButton;

    void AddComboItem(QComboBox* cmbo);
    bool event(QEvent * event);
    void wheelEvent(QWheelEvent* e);     //鼠标滑轮事件
private slots:
    void    onUpClicked();
    void    onDownClicked();
    void    OnLiftClicked();
    void    OnRightClicked();
    void    onLittleClicked();
    void    onBigClicked();


   void paintEvent(QPaintEvent *event);
public:
    explicit Widget();

    enum  Type {
        None          = 0,
        Amplification ,
        Shrink,
        Lift,
        Right,
        Up,
        Down,
        Move
    };

};
#endif // WIDGET_H

widget.cpp:

 

#include "widget.h"

Widget::Widget():
    BigButton("放大",this),
    LittleButton("缩小",this),
    LiftButton("向左",this),
    RightButton("向右",this),
    UpButton("向上",this),
    DownButton("向下",this),
    Paint(10,10,810,810),
    Alloffset(0,0),
    label("100%",this)
{
    ratio= 1.0;             //初始化图片缩放比例
    action = Widget::None;
    pixW = 985;            //设置图片尺寸为985*740
    pixH = 740;

    pix = new QPixmap;
    pix->load(":/pic/img.jpg");

    BigButton.setGeometry(822,10,60,25);
    connect(&BigButton,SIGNAL(clicked()),this,SLOT(onBigClicked()));

    LittleButton.setGeometry(822,40,60,25);
    connect(&LittleButton,SIGNAL(clicked()),this,SLOT(onLittleClicked()));

    LiftButton.setGeometry(822,70,60,25);
    connect(&LiftButton,SIGNAL(clicked()),this,SLOT(OnLiftClicked()));
    RightButton.setGeometry(822,100,60,25);
    connect(&RightButton,SIGNAL(clicked()),this,SLOT(OnRightClicked()));
    UpButton.setGeometry(822,130,60,25);
    connect(&UpButton,SIGNAL(clicked()),this,SLOT(onUpClicked()));
    DownButton.setGeometry(822,160,60,25);
    connect(&DownButton,SIGNAL(clicked()),this,SLOT(onDownClicked()));
    label.move(840,200);
    resize(890,850);

}

bool Widget::event(QEvent * event)
{
    static bool press=false;
    static QPoint PreDot;

    if(event->type() == QEvent::MouseButtonPress )
    {
           QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);

           //判断鼠标是否是左键按下,且鼠标位置是否在绘画区域
           if(mouse->button()==Qt::LeftButton &&Paint.contains(mouse->pos()))
           {
               press=true;
               QApplication::setOverrideCursor(Qt::OpenHandCursor); //设置鼠标样式

               PreDot = mouse->pos();
           }

    }
else if(event->type() == QEvent::MouseButtonRelease)
{
    QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);

    //判断鼠标是否是左键释放,且之前是在绘画区域
    if(mouse->button()==Qt::LeftButton && press )
    {
        QApplication::setOverrideCursor(Qt::ArrowCursor); //改回鼠标样式
        press=false;
    }
}

 if(event->type() == QEvent::MouseMove)              //移动图片
 {
      if(press)
     {
        QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);

        offset.setX(mouse->x() - PreDot.x());
        offset.setY(mouse->y() - PreDot.y());
        PreDot = mouse->pos();
        action = Widget::Move;
        this->update();
     }
 }
return QWidget::event(event);
}

void Widget::wheelEvent(QWheelEvent* event)     //鼠标滑轮事件
{
 if (event->delta()>0) {      //上滑,缩小

    action=Widget::Shrink;
    this->update();

 } else {                    //下滑,放大
     action=Widget::Amplification;
     this->update();
 }

 event->accept();
}



void Widget::paintEvent(QPaintEvent *event)
{
  QPainter painter(this);
  int NowW = ratio *pixW;
  int NowH = ratio *pixH;

if(action==Widget::Amplification)           //缩小
{
      ratio-=0.1*ratio;
    if(ratio<0.018)
      ratio = 0.01;

    /*显示比例*/
    QString str;
    str.sprintf("%.0f%",ratio*100);
    label.setText(str) ;
}
else  if(action==Widget::Shrink)           //放大
{

     ratio+=0.1*ratio;
   if(ratio>4.5)
     ratio = 5.000;

    /*显示比例*/
    QString str;
    str.sprintf("%.0f%",ratio*100);
    label.setText(str);
}
if(action==Widget::Amplification || action==Widget::Shrink)      //更新图片
{
  NowW = ratio *pixW;
  NowH = ratio *pixH;
  pix->load(":/pic/img.jpg");                 //重新装载,因为之前的图片已经被缩放过
  *pix = pix->scaled(NowW, NowH,Qt::KeepAspectRatio);
  action=Widget::None;

}

if(action==Widget::Move)                    //移动
{
    int offsetx=Alloffset.x()+offset.x();
    Alloffset.setX(offsetx);

    int offsety=Alloffset.y()+offset.y();
    Alloffset.setY(offsety);
    action=Widget::None;
}

if(abs(Alloffset.x())>=(Paint.width()/2 + NowW/2 -10))    //限制X偏移值
{
    if(Alloffset.x()>0)
        Alloffset.setX(Paint.width()/2 + NowW/2 -10);
    else
     Alloffset.setX(-Paint.width()/2 + -NowW/2 +10);
}
if(abs(Alloffset.y())>=(Paint.height()/2 + NowH/2 -10))    //限制Y偏移值
{
    if(Alloffset.y()>0)
        Alloffset.setY(Paint.height()/2 + NowH/2 -10);
    else
     Alloffset.setY(-Paint.height()/2 + -NowH/2 +10);

}

int x = Paint.width()/2 + Alloffset.x() -NowW/2;
if(x<0)
    x=0;

int y = Paint.height()/2 + Alloffset.y() -NowH/2;
if(y<0)
    y=0;

int  sx = NowW/2 - Paint.width()/2 - Alloffset.x();
if(sx<0)
    sx=0;

int  sy = NowH/2 - Paint.height()/2 - Alloffset.y();
if(sy<0)
    sy=0;

int w =(NowW - sx)>Paint.width()? Paint.width() : (NowW - sx);
if(w>(Paint.width()-x))
    w = Paint.width()-x;

int h =(NowH - sy)>Paint.height()? Paint.height() : (NowH - sy);
if(h>(Paint.height()-y))
    h = Paint.height()-y;

  painter.drawRect(Paint.x()-1,Paint.y()-1,Paint.width()+1,Paint.height()+1); //画框
  painter.drawTiledPixmap(x+Paint.x(),y+Paint.y(),w,h,*pix,sx,sy);             //绘画图形
}

void  Widget::onLittleClicked()
{
  action=Widget::Amplification;
  this->update();
}

void  Widget::onBigClicked()
{
  action=Widget::Shrink;
  this->update();
}
void Widget::onUpClicked()
{
  action=Widget::Move;
  offset.setX(0);
  offset.setY(-20);

  this->update();
}
void Widget::onDownClicked()
{
  action=Widget::Move;
  offset.setX(0);
  offset.setY(20);
  this->update();
}
void Widget::OnLiftClicked()
{
  action=Widget::Move;
  offset.setX(-20);
  offset.setY(0);

  this->update();
}
void Widget::OnRightClicked()
{
  action=Widget::Move;
  offset.setX(20) ;
  offset.setY(0) ;

  this->update();
}

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt,可以使用QPixmap来显示图片。要实现图片鼠标缩放鼠标拖动,可以使用以下步骤: 1. 创建一个QGraphicsView对象,并将其设置为可交互的。 2. 在QGraphicsView创建一个QGraphicsScene对象,并将其设置为QGraphicsView的场景。 3. 在QGraphicsScene创建一个QGraphicsPixmapItem对象,并将其设置为QGraphicsScene的项。 4. 加载需要显示的图片并设置到QGraphicsPixmapItem。 5. 实现鼠标滚轮事件,通过增加或减少QGraphicsPixmapItem的缩放因子来实现图片缩放。 6. 实现鼠标按下和拖动事件,通过改变QGraphicsPixmapItem的位置来实现图片拖动。 下面是具体的代码实现示例: ```cpp #include <QApplication> #include <QGraphicsScene> #include <QGraphicsView> #include <QGraphicsPixmapItem> #include <QPixmap> #include <QWheelEvent> #include <QPointF> #include <QMouseEvent> class ImageView : public QGraphicsView { public: ImageView(QWidget *parent = nullptr) : QGraphicsView(parent) { setInteractive(true); // 设置为可交互的 setDragMode(QGraphicsView::ScrollHandDrag); // 设置拖动模式为滚动拖动 m_pixmapItem = new QGraphicsPixmapItem; m_scene = new QGraphicsScene(this); m_scene->addItem(m_pixmapItem); setScene(m_scene); } void setPixmap(const QPixmap &pixmap) { m_pixmapItem->setPixmap(pixmap); // 设置显示的图片 setSceneRect(pixmap.rect()); // 设置场景大小为图片大小 } protected: void wheelEvent(QWheelEvent *event) override { const QPointF posSceneBefore = mapToScene(event->pos()); // 获取事件发生位置在场景的位置 const qreal factor = (event->angleDelta().y() > 0) ? 1.1 : 0.9; // 根据鼠标滚轮滚动方向计算缩放因子 m_pixmapItem->setScale(m_pixmapItem->scale() * factor); // 缩放图片 const QPointF posSceneAfter = mapToScene(event->pos()); // 获取事件发生位置在场景的位置 const QPointF posSceneDelta = posSceneAfter - posSceneBefore; // 计算场景位置的变化 centerOn(mapToScene(viewport()->rect().center()) - posSceneDelta); // 保持鼠标位置不变,调整视图心 } void mousePressEvent(QMouseEvent *event) override { if (event->button() == Qt::LeftButton) { m_lastPos = event->pos(); // 记录鼠标按下的位置 } QGraphicsView::mousePressEvent(event); } void mouseMoveEvent(QMouseEvent *event) override { if (event->buttons() & Qt::LeftButton) { const QPointF posSceneDelta = mapToScene(event->pos()) - mapToScene(m_lastPos); // 计算场景位置的变化 centerOn(mapToScene(viewport()->rect().center()) - posSceneDelta); // 调整视图心 m_lastPos = event->pos(); // 记录当前位置,供下次计算使用 } QGraphicsView::mouseMoveEvent(event); } private: QGraphicsPixmapItem *m_pixmapItem; QGraphicsScene *m_scene; QPoint m_lastPos; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); ImageView view; QPixmap pixmap(":/images/image.jpg"); view.setPixmap(pixmap); view.show(); return a.exec(); } ``` 在这个示例,我们创建了一个ImageView类继承自QGraphicsView。在构造函数,我们设置了一些初始属性,创建了一个QGraphicsPixmapItem对象和一个QGraphicsScene对象,并将QGraphicsPixmapItem添加到QGraphicsScene。在setPixmap函数,我们加载了一张图片,并设置到QGraphicsPixmapItem。 在wheelEvent函数,我们根据鼠标滚轮的滚动方向计算缩放因子,并使用setScale函数改变QGraphicsPixmapItem的缩放因子。然后,我们计算视图心在场景的位置的变化,并使用centerOn函数调整视图心,使鼠标位置保持不变。 在mousePressEvent函数和mouseMoveEvent函数,我们记录了鼠标按下和移动的位置,并根据位置的变化使用centerOn函数调整视图心,使图片实现拖动效果。 综上所述,通过这种方式,就可以实现图片鼠标缩放鼠标拖动的效果了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值