实现原理:接收widget的事件,paintEvent重绘地图,坐标比例什么的也是根据缩放和偏移量转换计算得出…
简单粗暴,直接上代码吧!
头文件:
#ifndef CPROJECTIONPICTURE_H
#define CPROJECTIONPICTURE_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class CProjectionPicture : public QWidget
{
Q_OBJECT
public:
CProjectionPicture(QWidget *parent = 0);
void setPicture(QPixmap & image);
protected:
bool event(QEvent *event) ;
void paintEvent(QPaintEvent *event) ;
void resizeEvent(QResizeEvent *e) ;
public Q_SLOTS:
void zoom(qreal scale); // 缩放 - scaleFactor:缩放的比例因子
void translate(QPointF delta); // 平移
void doubleClick();// 双击
signals:
void SignalDoPress(qreal x, qreal y);
private:
QPixmap currentImage;
int touch_status;//0 end and default,1press 2press move
qreal horizontalOffset;//水平偏移
qreal verticalOffset;//垂直偏移
qreal scaleFactor;//放大倍率
Qt::MouseButton m_translateButton; // 平移按钮
bool m_bMouseTranslate;
qreal m_zoomDelta; // 缩放的增量
QPoint m_lastMousePos; // 鼠标最后按下的位置
int pic_fix_width;//图片宽
int pic_fix_height;//图片长
QPointF current_zoom_center;
QPointF previous_touch_point0;
QPointF previous_touch_point1;
QTime touch_time;
bool touch_success;
QPushButton * button;
QGraphicsView * view;
};
#endif // CPROJECTIONPICTURE_H
CPP:
#include "cprojectionpicture.h"
#include
#include
#include
using namespace std;
CProjectionPicture::CProjectionPicture(QWidget *parent)
: QWidget(parent),
horizontalOffset(0),
verticalOffset(0),
scaleFactor(1),
m_translateButton(Qt::LeftButton),
m_bMouseTranslate(false),
m_zoomDelta(0.2)
{
//setWindowFlags(Qt::FramelessWindowHint);
this->setFocusPolicy(Qt::ClickFocus);
setFixedSize(1312,850);
grabGesture(Qt::PanGesture);
grabGesture(Qt::PinchGesture);
grabGesture(Qt::SwipeGesture);
current_zoom_center.setX((qreal)width()/2);
current_zoom_center.setY((qreal)height()/2);
touch_time.start();
touch_status=0;
touch_success=false;
}
void CProjectionPicture::setPicture(QPixmap &image)
{
// QGraphicsView vvv;
// QGraphicsScene scene;
// vvv.setScene(scene);
// QGraphicsPixmapItem item;
// item.scale();
// scene.addItem(item);
// item
currentImage = image;//image.convertToFormat(QImage::Format_RGB888);
pic_fix_width=currentImage.width();
pic_fix_height=currentImage.height();
scaleFactor=1;
button = new QPushButton(this);
button->setGeometry(100,100,100,100);
button->setText("button1");
update();
}
bool CProjectionPicture::event(QEvent *event)
{
switch (event->type()) {
case QEvent::Wheel:
{
QWheelEvent * wheelEvent = static_cast<QWheelEvent *>(event);
current_zoom_center.setX(wheelEvent->pos().x());
current_zoom_center.setY(wheelEvent->pos().y());
// qreal scale = 1;
// if()
// {
// currentScaleFactor =
// }
qreal currentScaleFactor=wheelEvent->delta() > 0?1.05:0.95;
zoom(currentScaleFactor);
return true;
}
case QEvent::MouseButtonPress:
{
QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
previous_touch_point0.setX(mouseEvent->pos().x());
previous_touch_point0.setY(mouseEvent->pos().y());
uint x = (mouseEvent->pos().x()-horizontalOffset)/scaleFactor;
uint y = (mouseEvent->pos().y()-verticalOffset)/scaleFactor;
qDebug("x = %d",x);
qDebug("y = %d",y);
if(button->x() < x && x < button->x()+button->width() &&
button->y() < y && y <button->y()+button->height())
{
qDebug("button1 pressed!!!");
}
return true;
}
case QEvent::MouseMove:
{
QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
// if(mouseEvent->MouseButtonPress)
// {
QPointF delta;
delta.setX(mouseEvent->pos().x()-previous_touch_point0.x());
delta.setY(mouseEvent->pos().y()-previous_touch_point0.y());
translate(delta);
previous_touch_point0.setX(mouseEvent->pos().x());
previous_touch_point0.setY(mouseEvent->pos().y());
// }
return true;
}
case QEvent::MouseButtonDblClick:
{
QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
current_zoom_center.setX(mouseEvent->pos().x());
current_zoom_center.setY(mouseEvent->pos().y());
doubleClick();
return true;
}
case QEvent::TouchBegin:
{
//1.获取第一次点击屏幕时的坐标
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
if(touchPoints.count()==1)
{
if(touchEvent->touchPointStates() & Qt::TouchPointPressed)
{
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.last();
previous_touch_point0.setX(touchPoint0.pos().x());
previous_touch_point0.setY(touchPoint0.pos().y());
touch_status=1;
}
}
else if(touchPoints.count()==2)
{
if(touchEvent->touchPointStates() & Qt::TouchPointPressed)
{
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();
previous_touch_point0.setX(touchPoint0.pos().x());
previous_touch_point0.setY(touchPoint0.pos().y());
previous_touch_point1.setX(touchPoint1.pos().x());
previous_touch_point1.setY(touchPoint1.pos().y());
touch_status=1;
}
}
return true;
}
case QEvent::TouchUpdate:
{
// 2.点击后的动作
qDebug() <<"TouchUpdate";
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
if (touchPoints.count() == 2)
{
if(touchEvent->touchPointStates() & Qt::TouchPointPressed)
{
touch_status=1;
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();
previous_touch_point0.setX(touchPoint0.pos().x());
previous_touch_point0.setY(touchPoint0.pos().y());
previous_touch_point1.setX(touchPoint1.pos().x());
previous_touch_point1.setY(touchPoint1.pos().y());
// 确定两点之前的中心点的坐标,后续区域缩放的时候使用这个中心点作为 缩放定位
current_zoom_center.setX((touchPoint0.pos().rx()+touchPoint1.pos().rx())/2);
current_zoom_center.setY((touchPoint0.pos().ry()+touchPoint1.pos().ry())/2);
}
else if(touchEvent->touchPointStates() & Qt::TouchPointMoved)
{
touch_status=2;
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();
current_zoom_center.setX((touchPoint0.pos().rx()+touchPoint1.pos().rx())/2);
current_zoom_center.setY((touchPoint0.pos().ry()+touchPoint1.pos().ry())/2);
qreal qlines=
QLineF(touchPoint0.pos(), touchPoint1.pos()).length()
/ QLineF(previous_touch_point0, previous_touch_point1).length();
qreal currentScaleFactor=qlines>1?1.05:0.95;
zoom(currentScaleFactor);
previous_touch_point0.setX(touchPoint0.pos().x());
previous_touch_point0.setY(touchPoint0.pos().y());
previous_touch_point1.setX(touchPoint1.pos().x());
previous_touch_point1.setY(touchPoint1.pos().y());
}
else if(touchEvent->touchPointStates() & Qt::TouchPointReleased)
{
touch_status=0;
}
}
else if(touchPoints.count()==1)
{
if(touchEvent->touchPointStates() & Qt::TouchPointPressed)
{
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.last();
previous_touch_point0.setX(touchPoint0.pos().x());
previous_touch_point0.setY(touchPoint0.pos().y());
touch_status=1;
}
else if(touchEvent->touchPointStates() & Qt::TouchPointMoved)
{
touch_status=2;
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.last();
QPointF delta;
delta.setX(touchPoint0.pos().x()-previous_touch_point0.x());
delta.setY(touchPoint0.pos().y()-previous_touch_point0.y());
translate(delta);
previous_touch_point0.setX(touchPoint0.pos().x());
previous_touch_point0.setY(touchPoint0.pos().y());
}
else if(touchEvent->touchPointStates() & Qt::TouchPointReleased)
{
}
}
return true;
}
case QEvent::TouchEnd:
{
//3. 松开
qDebug() <<"TouchEnd";
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
if(touchPoints.count()==1)
{
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
if(touch_status==1)
{
int timecount= touch_time.restart();
if(timecount<500)
{
if(!touch_success)
{
current_zoom_center.setX(touchPoint0.pos().rx());
current_zoom_center.setY(touchPoint0.pos().ry());
if(scaleFactor>1.5)
{
zoom(true);
}
else
{
zoom(true);
}
touch_success=true;
}
}
else
{
touch_success=false;
qreal sx= touchPoint0.pos().rx();
qreal sy= touchPoint0.pos().ry();
qreal rx=(sx-horizontalOffset)*scaleFactor;
qreal ry=(sy-verticalOffset)*scaleFactor;
emit SignalDoPress(rx,ry);
}
}
}
touch_status=0;
return true;
}
default:
break;
}
return QWidget::event(event);
}
void CProjectionPicture::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QPixmap image = currentImage;
// scaleFactor = 1.5;
if(!image.isNull()){
image = image.scaled(this->width() * scaleFactor,
this->height() * scaleFactor,
Qt::KeepAspectRatio,
Qt::FastTransformation);
}
const qreal iw = image.width();
const qreal ih = image.height();
// const qreal wh = height();
// const qreal ww = width();
//cout<
if(horizontalOffset>0)
{
horizontalOffset=0;
}
if(verticalOffset>0)
{
verticalOffset=0;
}
if(this->width()-horizontalOffset>iw)
{
horizontalOffset=this->width()-iw;
}
if(this->height()-verticalOffset>ih)
{
verticalOffset=this->height()-ih;
}
painter.drawPixmap(horizontalOffset,verticalOffset,image);
// button->resize(scaleFactor*button->size());
// button->move(horizontalOffset,verticalOffset);
// painter.drawImage(-200,-2\0,image);
}
void CProjectionPicture::resizeEvent(QResizeEvent*e)
{
update();
QWidget::resizeEvent(e);
}
// 缩放 - scaleFactor:缩放的比例因子
void CProjectionPicture::zoom(qreal scale)
{
// qreal scalecur = scale ? scaleFactor+0.2 : scaleFactor-0.2;
// scale ? scalecu = scaleFactor+0.1 : scalecu = scaleFactor-0.1;
qreal scalecur=scaleFactor*scale;
QPointF current_center=current_zoom_center;
// if(scalecur
// {
// scalecur=fix_scaleFactor;
// horizontalOffset=0;
// verticalOffset=0;
// }
if(scalecur<1)
{
scalecur=1;
horizontalOffset=0;
verticalOffset=0;
}
else if(scalecur>2)
{
scalecur=2;
horizontalOffset = current_center.rx() -(current_center.rx() - horizontalOffset)*scalecur/scaleFactor;
verticalOffset = current_center.ry() -(current_center.ry() - verticalOffset)*scalecur/scaleFactor;
}
else
{
horizontalOffset = current_center.rx() -(current_center.rx() - horizontalOffset)*scalecur/scaleFactor;
verticalOffset = current_center.ry() -(current_center.ry() - verticalOffset)*scalecur/scaleFactor;
}
scaleFactor = scalecur;
// QImage img(QString("tvm.bkg.00.chn.%1.jpg").arg(scaleFactor));
// currentImage = img.convertToFormat(QImage::Format_RGB888);
// pic_fix_width=currentImage.width();
// pic_fix_height=currentImage.height();
update();
}
// 平移
void CProjectionPicture::translate(QPointF delta)
{
horizontalOffset +=delta.x();
verticalOffset += delta.y();
update();
}
void CProjectionPicture::doubleClick()
{
scaleFactor > 1 ? scaleFactor = 1 : scaleFactor = 2;
if(scaleFactor == 1)
{
horizontalOffset=0;
verticalOffset=0;
}
else
{
QPointF current_center=current_zoom_center;
horizontalOffset = current_center.rx() -(current_center.rx() - horizontalOffset)*scaleFactor;
verticalOffset = current_center.ry() -(current_center.ry() - verticalOffset)*scaleFactor;
}
// QImage img(QString("tvm.bkg.00.chn.%1.jpg").arg(scaleFactor));
// currentImage = img.convertToFormat(QImage::Format_RGB888);
// pic_fix_width=currentImage.width();
// pic_fix_height=currentImage.height();
update();
}
使用:
main.cpp
#include "widget.h"
#include
#include "cprojectionpicture.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Widget w;
// w.show();
CProjectionPicture cpij;
QPixmap img("ditu.jpg");//一张高清地图
cpij.setPicture(img);
cpij.show();
return a.exec();
}
关于坐标比例问题:文章中代码实现了地图缩放拖动后的点击地图上的点相对屏幕坐标还是不变
case QEvent::MouseButtonPress:
{
QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
previous_touch_point0.setX(mouseEvent->pos().x());
previous_touch_point0.setY(mouseEvent->pos().y());
uint x = (mouseEvent->pos().x()-horizontalOffset)/scaleFactor;
uint y = (mouseEvent->pos().y()-verticalOffset)/scaleFactor;
qDebug("x = %d",x);
qDebug("y = %d",y);
if(button->x() < x && x < button->x()+button->width() &&
button->y() < y && y <button->y()+button->height())
{
qDebug("button1 pressed!!!");
}
return true;
}