先看效果:
(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);

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

被折叠的 条评论
为什么被折叠?



