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 :

    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;

    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);
           press=true;
           PreDot = mouse->pos();

    }
    else if(event->type() == QEvent::MouseButtonRelease)
    {
        if(press)
            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);
    QPixmap  pix;

    pix.load(":/pic/img.jpg");

    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) ;

        action=Widget::None;
    }
    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);

        action=Widget::None;
    }

    int NowW = ratio *pixW;
    int NowH = ratio *pixH;

    if(action==Widget::Move)                    //移动
    {
        int offsetx=Alloffset.x()+offset.x();
        if(abs(offsetx)>=(Paint.width()/2 + NowW/2 -10))    //限制X偏移值
        {
            if(offsetx>0)
                offsetx = Paint.width()/2 + NowW/2 -10;
            else
                offsetx= -Paint.width()/2 + -NowW/2 +10;
        }
        Alloffset.setX(offsetx);

        int offsety=Alloffset.y()+offset.y();
        if(abs(offsety)>=(Paint.height()/2 + NowH/2 -10))    //限制Y偏移值
        {
            if(offsety>0)
                offsety = Paint.height()/2 + NowH/2 -10;
            else
                offsety= -Paint.height()/2 + -NowH/2 +10;
        }

         Alloffset.setY(offsety);
         action=Widget::None;
    }

    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;

    pix = pix.scaled(NowW, NowH,Qt::KeepAspectRatio);
    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();
}

原文地址:https://www.cnblogs.com/lifexy/p/9057046.html

时间: 2024-10-08 21:45:50

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

Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动)

※效果 ※使用到的开源库 PhotoView 图片缩放:支持双击缩放,手指捏拉缩放 https://github.com/chrisbanes/PhotoView Universalimageloader 图片下载缓存库 https://github.com/nostra13/Android-Universal-Image-Loader ViewPagerIndicator 分页指示器 https://github.com/JakeWharton/Android-ViewPagerIndicat

Android实现图片的缩放和拖动

概述:通过自定义ImageView控件,在xml布局里面调用自定的组件实现图片的缩放. /** * 自定义的ImageView控制,可对图片进行多点触控缩放和拖动 * * @author qiuwanyong */ public class MyImageView extends ImageView { /** * 初始化状态常量 */ public static final int STATUS_INIT = 1; /** * 图片放大状态常量 */ public static final i

QPixmap,QImage图片大小缩放linux版

注意事项: 1.装载图片的地址有时候会读取不到.可以多摸索一下当前系统对应的格式. 2.scaled缩放方式选择 3.注意保存路径.下面程序保存路径是当前执行文件目录中. PicOpera::PicOpera(QObject *parent) : QObject(parent){    QPixmap pixmap;    pixmap.load("/home/arikes/Programer/Qt/ImageOpera/aa.jpg");    QPixmap fitpixmap=p

Android中View(视图)绘制不同状态背景图片原理深入分析以及StateListDrawable使用详解

今天继续给大家分享下View的相关知识,重点有一下两点:   1.View的几种不同状态属性            2.如何根据不同状态去切换我们的背景图片. 开篇介绍:android背景选择器selector用法汇总 对Android开发有经验的同学,对 <selector>节点的使用一定很熟悉,该节点的作用就是定义一组状态资源图片,使其能够 在不同的状态下更换某个View的背景图片.例如,如下的hello_selection.xml文件定义: <?xml version="

使用CSS、JavaScript及Ajax实现图片预加载的方法详解 

预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验.本文将分享使用CSS.JavaScript及Ajax实现图片预加载的三个不同技术,来增强网站的性能与可用性.一起来看看吧,希望对大家学习web前端有所帮助. 方法一:用CSS和JavaScript实现预加载 实现预加载图片有很多方法,包括使用CSS

php上传文件与图片到七牛的实例详解

上传文件到七牛最简单的方式就是使用七牛官方最新的SDK 用composer安装PHP SDK composer require qiniu/php-sdk 上传文件到七牛 use Qiniu\Auth;use Qiniu\Storage\UploadManager; $cfg = [ 'access' => 'YOUR_ACCESS_KEY', 'secret' => 'YOUR_SECRET_KEY', 'bucket' => 'YOUR_BUCKET', 'domain' =>

IOS UIScrollView详解 & 图片缩放功能

一 UIScrollView 简介 UIScrollView是能滚动的视图控件,可以通过滚动的方式来展示类容. 二 UIScrollView常见属性 //设置UIScrollView滚动的位置 @property(nonatomic) CGPoint contentOffset;  //设置UIScrollView内容的尺寸,滚动范围 @property(nonatomic) CGSize contentSize;  //设置UIScrollView的4周增加额外的滚动区域 @property(

鼠标滚轮实现图片的缩放-------Day79

今天是7月的最后一天了,不得不说,我定下的七月份剩余几天的计划是完不成了,一则工作确实紧了些,再则没能处理好生活.工作和学习的节奏,这才是人生最大的课题吧,不过也还好,至少自己还在坚持着,其实真的越来越感觉到自己的不足,可昂扬的斗志却是越来越低沉的迹象,内心里总有个声音在蛊惑自己:别整那些刻意的东西,做给谁看啊,而且刻意的记录的时间完全可以拿来学更多的东西,可最终我还在这个蛊惑前坚持着:确实可以腾出更多的时间来,也没人会在意在做什么,可是,同样,我不需要走那么快,而且只要知道自己在意就好了,我需

Discuz升级!图片查看插件(支持鼠标缩放、实际大小、旋转、下载)

图片查看是网站中的常用功能,用于展示详细的图片.在discuz图片插件的基础上进行了改造,因此这篇文章主要从以下几个方面来讨论图片查看插件.希望可以帮助到大家,有不对的地方也欢迎大家给以正确的指导. (1)discuz的实现过程及效果 (2)discuz的局限性 (3)discuz的改进步骤 (4)兼容性及最后效果 (5)总结(常见问题) demo示例:http://zyk3.ataw.cn/discuz/index.html 一.discuz的实现过程及效果 点击图片,弹出层有大图,同时有在新