qt,QGraphicsView实现鼠标中键拖动图片,鼠标滚轮缩放、两个窗口联动左键选点等功能(c++&pyqt两个版本)

该博客介绍了如何使用C++和PyQt分别实现图像在QGraphicsView中拖动、缩放以及选点功能,并实现窗口间的联动。在C++版本中,通过重写QGraphicsView类,实现了鼠标中键拖动、滚轮缩放、左键选点和右键完成区域选择。在PyQt版本中,同样重写了QGraphicsView类,支持了numpy矩阵作为图像输入,并实现了类似的功能。此外,两个版本都支持了窗口间的图像显示同步和选点操作联动。

先看效果

(1)c++版本(一个动图)

(2)pyqt版本(一个图):与c++版本一毛一样,用的同一个ui文件,此处动图略

 实现关键点:1)拖动:重写QGraphicsView类,鼠标中键按下记录位置并更改鼠标样式为手型,鼠标中键弹起记录鼠标位置,并执行拖动,通过设置横竖滚动条位置实现拖动;2)缩放:重写鼠标滚轮滑动事件滚轮上滑放大,下滑缩小即可;3)联动:设置联动参数,一个当前缩放参数,两个当前横竖滚轮位置参数。通过这三个参数进行联动;4)选点:左键选点,左键勾勒区域折点,右键停止并自动封闭。

源代码——c++版本

步骤(关键在于QgraphicsView类的重写,所有功能的实现均封装在这个类里边

(1)打开qtcreater,新建一个空的qt Application项目,并添加两个QgraphicsView控件用于显示图片,与一个textedit控件用于输出选点内容,并设置好布局

(2)改写QGraphicsView类,新建一个MyQGraphicsView类,继承QGraphicsView类,新建的这个类对应的头文件MyQGraphicsView.h如下:

#ifndef MYQGRAPHICSVIEW_H
#define MYQGRAPHICSVIEW_H
#pragma execution_character_set("UTF-8")
#include <QKeyEvent>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QMouseEvent>
#include <QScrollBar>
#include <QPen>
#include <vector>

class MyQGraphicsView: public QGraphicsView
{
private:
    QPointF GetMeanPos(std::vector<QPointF> data);//获取一组点中间位置

protected:
    void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
private:
    double m_scalnum; //缩放系数
    QPointF m_startpos; //鼠标中建开始点
    QPointF m_endpos; //鼠标中建结束点
    double m_posx; //视图移动参数x
    double m_posy; //试图移动参数y
    int m_flag; //是否进行选点
    int m_linkflag; //是否进行联动
    MyQGraphicsView *m_linkgraphicsview; //进行联动的窗口
    std::vector<QPointF> m_points; //选择的点
    std::vector<std::vector<QPointF>> m_allpoints; //选择的所有点

public:
    explicit MyQGraphicsView(QWidget *parent = 0);
    void SetImage(QImage img);
    // 设置是否进行联动
    void SetLinkFlag(int flag)
    {
        m_linkflag = flag;
    }
    //设置联动窗口
    void SetLinkWidget(MyQGraphicsView *graphicsview)
    {
        m_linkgraphicsview = graphicsview;
    }
    // 设置联动参数
    void SetLinkPara(double para[3]);
    // 获取联动参数
    double* GetLinkPara()
    {
        double *para = new double[3];
        para[0] = m_scalnum;
        para[1] = m_posx;
        para[2] = m_posy;
        return para;
    }
    // view初始化
    void InitializeView()
    {
        m_points.clear();
        m_allpoints.clear();
        m_flag = 0;
        m_scalnum = 1;
        this->setCursor(Qt::ArrowCursor);
    }
    //设置是否选点
    void SetChoosePoint(int flag)
    {
        m_flag = flag;
        if (flag == 0)
        {
            this->setCursor(Qt::ArrowCursor);
        }
        else if (flag == 1 || flag == 2)
        {
            this->setCursor(Qt::CrossCursor);
        }
    }
    //获取当前选点状态
    int GetFlag()
    {
        return m_flag;
    }
    //获取单个区域点集
    std::vector<QPointF> GetPoints()
    {
        return m_points;
    }
    //删除单个点集
    void ClearPoints()
    {
        m_points.clear();
    }
    //获取所有点集
    std::vector<std::vector<QPointF>> GetAllPoints()
    {
        return m_allpoints;
    }
    //删除所有点集
    void CalerAllPoints()
    {
        m_allpoints.clear();
    }
};

#endif // MYQGRAPHICSVIEW_H

 新建的这个类对应的头文件MyQGraphicsView.cpp如下:

#include "MyQGraphicsView.h"
#include <QDebug>

MyQGraphicsView::MyQGraphicsView(QWidget *parent):
    QGraphicsView(parent)
{
    //设置鼠标样式
//    setCursor(Qt::CrossCursor);
    //使用抗锯齿渲染
//    setRenderHint(QPainter::Antialiasing);
    //设置缓冲背景,加速渲染
//    setCacheMode(QGraphicsView::CacheBackground);
//    setStyleSheet("border: 1px solid black");
//    setAlignment(Qt::AlignVCenter | Qt::AlignTop);
//    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_scalnum = 1.;
    m_flag = 0;
    setMouseTracking(true);
}

void MyQGraphicsView::SetLinkPara(double para[3])
{
    double scalenum = para[0];
    double posx = para[1];
    double posy = para[2];
    //设置缩放
    if (scalenum > m_scalnum)
    {
        this->scale(1.3, 1.3);
        m_scalnum *= 1.3;
    }
    else if (scalenum < m_scalnum)
    {
        this->scale(1/1.3, 1/1.3);
        m_scalnum /= 1.3;
    }
    //设置移动
    if (posx != m_posx && posy != m_posy)
    {
        this->horizontalScrollBar()->setValue(posx);
        this->verticalScrollBar()->setValue(posy);
        m_posx = posx;
        m_posy = posy;
    }
}

void MyQGraphicsView::wheelEvent(QWheelEvent *event)
{
    if(event->delta()>0)
    {
        this->scale(1.3, 1.3);
        m_scalnum *= 1.3;
    }
    else
    {
        this->scale(1/1.3, 1/1.3);
        m_scalnum /= 1.3;
    }
    if (m_linkflag == 1)
    {
        m_linkgraphicsview->SetLinkPara(this->GetLinkPara());
    }
    QGraphicsView::wheelEvent(event);
}


void MyQGraphicsView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::MiddleButton)
    {
        this->setCursor(Qt::PointingHandCursor);
        m_startpos = mapToScene(event->pos());
    }
    //鼠标左键选点并画线
    else if (event->button() == Qt::LeftButton && m_flag == 1)
    {
        QPointF p = this->mapToScene(event->pos());
//        qDebug()<<p;
        m_points.push_back(p);
        //绘制点
        QPen *pen = new QPen();
        pen->setColor(QColor(255, 0, 0));
        pen->setWidth(2);
      
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值