• 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();
    }
  • 相关阅读:
    躺着的人
    (转载)CentOS查看系统信息|CentOS查看命令
    (转载)重新介绍 JavaScript(JS 教程)
    (转载)Java 容器 & 泛型:四、Colletions.sort 和 Arrays.sort 的算法
    (转载)Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较
    (转载)Java 容器 & 泛型:二、ArrayList 、LinkedList和Vector比较
    (转载)Java 容器 & 泛型:一、认识容器
    (转载)Python IDLE reload(sys)后无法正常执行命令的原因
    jmete 取配置文件的行数(二)
    jmete 取配置文件的行数(一)
  • 原文地址:https://www.cnblogs.com/lifexy/p/9057046.html
Copyright © 2020-2023  润新知