20.QT-Qpixmap实现图片鼠标缩放,鼠标拖动示例(详解)
时间:2022-05-30
本文章向大家介绍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);
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);
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();
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;
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();
}
- 小程序审核攻略
- js checkbox.checked=true在document.body.appendChild(checkbox)前与后赋值
- 吹得飞起的人工智能,2017都摔过哪些跟头?
- 排序还可以这样做
- 韩政府公布虚拟货币投机行为打击对策
- SqlServer2005数据库文件损坏的拯救过程
- 2017年,人类在自己设计的所有游戏中都败给了AI,无一幸免
- 测试组,请用VSS命令行获取最新版本
- 想起温习一下JS中的this apply call arguments
- 学习利用JSON 摆脱表单与业务对象双向转换的繁琐工作
- 代码也疯狂:diagram生成流程图
- 设置你的Gravatar头像的方法
- 阅读Ext 学习Javascript(二)Core/Ext.extend 从继承说起
- IronPython资料
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Codeforces 660C-Hard Process【尺取法练习】
- 杭电5178 (二分练习!)
- Java 13 新特性
- 杭电 1789(贪心思维练习)
- 利用反转函数确定回文串
- Codeforces Round #618 (Div. 2)
- Educational Codeforces Round 82 (Rated for Div. 2)
- [C# 开发技巧]如何防止程序多次运行
- 问题 1117: K-进制数
- Java 11 新垃圾回收器 ZGC
- Red and Black(DFS 深搜练习)
- Codeforces Round #619 (Div. 2)
- 问题 1255: [蓝桥杯][算法提高]能量项链
- C# 开发技巧]如何防止程序多次运行 线程 进程
- 问题 1433: [蓝桥杯][2013年第四届真题]危险系数