Qt触摸放大、缩小、拖拽图像

13 篇文章 0 订阅

实现原理:接收widget的事件,paintEvent重绘地图,坐标比例什么的也是根据缩放和偏移量转换计算得出…
简单粗暴,直接上代码吧!

//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLoggingCategory>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QPixmap>
#include <QObject>
#include <QWidget>
#include <QGraphicsView>
#include <QEvent>
#include <QTouchEvent>
#include <QDebug>
#include <QMouseEvent>
#include <QPixmap>
#include <QTime>
#include <QPushButton>


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void setPicture(QPixmap& image);
    void zoom(qreal scale);
    void translate(QPointF delta);
    void doubleClick();
protected:
    bool event(QEvent *event) override;

    void paintEvent(QPaintEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;
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;

    Ui::MainWindow *ui;   
};
#endif // MAINWINDOW_H

//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
    QPixmap img("/home/one/01-QtTest/TouchTest3/brightenhance.bmp");
    //QPixmap img("./brightenhance.bmp");
    setPicture(img);
    setAttribute(Qt::WA_AcceptTouchEvents,true);
    setFocusPolicy(Qt::ClickFocus);
    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;
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setPicture(QPixmap &image)
{
    currentImage = image;//image.convertToFormat(QImage::Format_RGB888);
    pic_fix_width=currentImage.width();
    pic_fix_height=currentImage.height();

    scaleFactor=1;
    update();
}

void MainWindow::zoom(qreal scale)
{
    qreal scalecur=scaleFactor*scale;
    QPointF current_center=current_zoom_center;

    if(scalecur < 1)
    {
        scalecur = 1;
        horizontalOffset=0;
        verticalOffset=0;
    }
    else if(scalecur > 3)
    {
        scalecur = 3;
        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;
    update();
}

void MainWindow::translate(QPointF delta)
{
    horizontalOffset +=delta.x();
    verticalOffset += delta.y();
    update();
}

void MainWindow::doubleClick()
{
    scaleFactor = scaleFactor > 1 ? scaleFactor = 1 : scaleFactor = 3;
    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;
    }
    update();
}

bool MainWindow::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 currentScaleFactor = wheelEvent->delta() > 0 ? 1.1 : 0.9;
        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);
        return true;
    }
    case QEvent::MouseMove:
    {
        QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
         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:
    {
        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.1 : 0.9;

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

                        zoom(true);

                        touch_success=true;
                    }
                }

            }
        }
        touch_status=0;
        return true;
    }
    default:
        break;
    }
    return QWidget::event(event);
}



void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPixmap image = currentImage;
    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();
    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);
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    update();
    QWidget::resizeEvent(event);
}
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Qt中实现无边框放大缩小拖动界面可以使用以下方法: 1. 设置窗口无边框 使用setWindowFlags()函数设置窗口无边框,示例代码如下: ```python self.setWindowFlags(Qt.FramelessWindowHint) ``` 2. 实现窗口放大缩小 使用QDesktopWidget类获取屏幕的宽度和高度,然后通过setGeometry()函数设置窗口的大小,示例代码如下: ```python desktop = QApplication.desktop() width = desktop.width() height = desktop.height() self.setGeometry(0, 0, width, height) ``` 3. 实现窗口拖动 重载鼠标事件函数,实现窗口的拖动功能。在mousePressEvent()函数中记录鼠标按下时的位置,然后在mouseMoveEvent()函数中计算鼠标移动的距离,将窗口移动到相应的位置,示例代码如下: ```python def mousePressEvent(self, event): self.mouse_pos = event.globalPos() - self.pos() def mouseMoveEvent(self, event): self.move(event.globalPos() - self.mouse_pos) ``` 完整代码示例: ```python from PyQt5.QtWidgets import QApplication, QWidget from PyQt5.QtCore import Qt class MainWindow(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowFlags(Qt.FramelessWindowHint) self.setGeometry(0, 0, 800, 600) self.show() def mousePressEvent(self, event): self.mouse_pos = event.globalPos() - self.pos() def mouseMoveEvent(self, event): self.move(event.globalPos() - self.mouse_pos) if __name__ == '__main__': app = QApplication([]) window = MainWindow() app.exec_() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值