先看效果:
(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
#include
#include
#include
#include
#include
#include
#include
class MyQGraphicsView: public QGraphicsView
{
private:
QPointF GetMeanPos(std::vector 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 m_points; //选择的点
std::vector> 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 GetPoints()
{
return m_points;
}
//删除单个点集
void ClearPoints()
{
m_points.clear();
}
//获取所有点集
std::vector> GetAllPoints()
{
return m_allpoints;
}
//删除所有点集
void CalerAllPoints()
{
m_allpoints.clear();
}
};
#endif // MYQGRAPHICSVIEW_H
新建的这个类对应的头文件MyQGraphicsView.cpp如下:
#include "MyQGraphicsView.h"
#include
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()<setColor(QColor(255, 0, 0));
pen->setWidth(2);
this->scene()->addEllipse(p.x()-1, p.y()-1, 2, 2, *pen);
int num = m_points.size();
//绘制线
if (num >= 2)
{
pen->setColor(QColor(241, 89, 42));
pen->setWidth(1);
this->scene()->addLine(m_points[num-2].x(),
m_points[num-2].y(),
m_points[num-1].x(),
m_points[num-1].y(),
*pen);
}
}
//鼠标左键只选点
else if (event->button() == Qt::LeftButton && m_flag == 2)
{
QPointF p = this->mapToScene(event->pos());
m_points.push_back(p);
//画点
QPen *pen = new QPen();
pen->setColor(QColor(255, 0, 0));
pen->setWidth(2);
this->scene()->addEllipse(p.x()-1, p.y()-1, 4, 4, *pen);
//添加文本
QFont *font = new QFont("Roman times", 20, QFont::Bold);
QGraphicsTextItem *text = new QGraphicsTextItem(QString::number(m_points.size()));
text->setPos(p.x()-10, p.y()-10);
text->setDefaultTextColor(QColor(248, 201, 0));
text->setFont(*font);
this->scene()->addItem(text);
}
//鼠标右键完成当前区域选点
else if (event->button() == Qt::RightButton && m_flag == 1)
{
m_allpoints.push_back(m_points);
//连接终点与起点
QPen *pen = new QPen();
pen->setColor(QColor(241, 89, 42));
pen->setWidth(1);
int num = m_points.size() - 1;
// qDebug()<scene()->addLine(m_points[num].x(),
m_points[num].y(),
m_points[0].x(),
m_points[0].y(),
*pen);
//添加文本
QFont *font = new QFont("Roman times", 20, QFont::Bold);
QGraphicsTextItem *text = new QGraphicsTextItem(QString::number(m_allpoints.size()));
QPointF mpos = GetMeanPos(m_points);
text->setPos(mpos.x()-20, mpos.y()-20);
text->setDefaultTextColor(QColor(248, 201, 0));
text->setFont(*font);
this->scene()->addItem(text);
//清除已经选好的点集
m_points.clear();
}
QGraphicsView::mousePressEvent(event);
}
void MyQGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
//鼠标中建弹起进行视图移动
if (event->button() == Qt::MiddleButton)
{
if (m_flag != 0)
this->setCursor(Qt::CrossCursor);
else
this->setCursor(Qt::ArrowCursor);
m_endpos = mapToScene(event->pos());
//获取滚动条当前位置
double oposx = this->horizontalScrollBar()->value();
double oposy = this->verticalScrollBar()->value();
//计算鼠标移动的距离
QPointF offset = m_endpos - m_startpos;
//计算新的滚轮位置
double nposx = oposx-offset.x()*m_scalnum;
double nposy = oposy-offset.y()*m_scalnum;
//设置新的滚轮位置
this->horizontalScrollBar()->setValue(nposx);
this->verticalScrollBar()->setValue(nposy);
// QPointF offset = -m_endpos + m_startpos;
// this->scene()->setSceneRect(this->scene()->sceneRect().x()+offset.x(),
// this->scene()->sceneRect().y()+offset.y(),
// this->scene()->sceneRect().width(),
// this->scene()->sceneRect().height());
this->scene()->update();
//记录备用
m_posx = nposx;
m_posy = nposy;
//进行联动
if (m_linkflag == 1)
{
m_linkgraphicsview->SetLinkPara(this->GetLinkPara());
}
}
QGraphicsView::mouseReleaseEvent(event);
}
void MyQGraphicsView::SetImage(QImage img)
{
//把影像添加到画布
QPixmap Images = QPixmap::fromImage(img);
QGraphicsPixmapItem *map = new QGraphicsPixmapItem(Images);
// map = new QGraphicsPixmapItem(Images);
map->setFlag(QGraphicsPixmapItem::ItemIsSelectable, true);
map->setFlag(QGraphicsPixmapItem::ItemIsMovable, false);
map->setFlag(QGraphicsPixmapItem::ItemSendsGeometryChanges,true);
QGraphicsScene *scene = new QGraphicsScene(); //场景 = new QGraphicsScene();
//画布添加至场景
scene->addItem(map);
//场景绑定到控件
this->setScene(scene);
this->show();
}
QPointF MyQGraphicsView::GetMeanPos(std::vector data)
{
double sumx(0);
double sumy(0);
for (int i(0); i
(3)将原有新建的QGraphicsView控件提升为新建的类
(4)在主窗体构造函数中添加以下内容:
QgraphicsViewTestGUI::QgraphicsViewTestGUI(QWidget *parent)
: QWidget(parent)
, ui(new Ui::QgraphicsViewTestGUI)
{
ui->setupUi(this);
//窗口最大化
showMaximized();
//设置事件过滤器,用于选点测试
ui->graphicsView_LeftImage->viewport()->installEventFilter(this);
ui->graphicsView_RightImage->viewport()->installEventFilter(this);
//设置窗口比例
ui->splitter->setStretchFactor(0, 4);
ui->splitter->setStretchFactor(1, 1);
//设置联动
ui->graphicsView_LeftImage->SetLinkFlag(1);
ui->graphicsView_RightImage->SetLinkFlag(1);
ui->graphicsView_LeftImage->SetLinkWidget(ui->graphicsView_RightImage);
ui->graphicsView_RightImage->SetLinkWidget(ui->graphicsView_LeftImage);
//显示图片
QImage img1("E:/smallthings/temp/QgraphicsViewTestGUI/testimg.jpg");
QImage img2("E:/smallthings/temp/QgraphicsViewTestGUI/testimg.jpg");
ui->graphicsView_LeftImage->SetImage(img1);
ui->graphicsView_RightImage->SetImage(img2);
//设置选点
ui->graphicsView_LeftImage->SetChoosePoint(2);//左边窗口测试选点
ui->graphicsView_RightImage->SetChoosePoint(1);//右边窗口测试选区域
}
(5)在主窗体类中添加两个函数
函数声明:
bool eventFilter(QObject* watched, QEvent* event);//事件过滤
void ShowMsg(QString msg);//显示日志
函数实现:
bool QgraphicsViewTestGUI::eventFilter(QObject* watched, QEvent* event)
{
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mouseevent = static_cast(event);
if(mouseevent->button() == Qt::LeftButton && watched == ui->graphicsView_LeftImage->viewport())
{
//左窗口测试选点(左键)
std::vector ps = ui->graphicsView_LeftImage->GetPoints();
if (ps.size() != 0)
{
QPointF nowp = ps.at(ps.size() - 1);
ShowMsg("影像选点测试,影像上一个点第" +
QString::number(ps.size()) +
"个点,坐标为:(" +
QString::number(nowp.x(), 'f', 3) +
"," +
QString::number(nowp.y(), 'f', 3) + ")");
}
}
else if(mouseevent->button() == Qt::RightButton && watched == ui->graphicsView_RightImage->viewport())
{
//右键测试选区域(右键)
std::vector> areas = ui->graphicsView_RightImage->GetAllPoints();
if (areas.size() != 0)
{
std::vector nowarea = areas.at(areas.size() - 1);
QString coorstr = "";
for (int i(0); itextBrowser_log->moveCursor(QTextCursor::End);
ui->textBrowser_log->append(">>" + msg);
}
(6)愉快的运行
源代码——pyqt版本:
依赖项:
PyQt5 == 5.10.1
numpy == 1.21.4
qimage2ndarray == 1.8.3
步骤(关键在于QgraphicsView类的重写,所有功能的实现均封装在这个类里边):
(1)新建一个python脚本,里边新建一个MyQgraphicsView类,继承QgraphicsView类,添加如下代码。注:pyqt版本支持的影像为numpy矩阵,可以是多通道的遥感影像,但默认前三个通道为RGB;数据类型可以不是uint8(比如uint16),会自动进行2%线性拉伸,去除过大、过小的异常值,同时数据拉伸到uint8范围内
# yangzhen
# 2021.12.04
from PyQt5 import QtCore as qc
from PyQt5 import QtGui as qg
from PyQt5 import QtWidgets as qw
import numpy as np
import copy
class MyQGraphicsView(qw.QGraphicsView):
def __init__(self, parent):
super(MyQGraphicsView, self).__init__(parent)
self.setMouseTracking(True)
self.points = [] # 选择的点
self.allpoints = []
self.startpos = qc.QPoint(0, 0) # 鼠标中键按下时起始点
self.endpos = qc.QPoint(0, 0) # 鼠标中键弹起时终点
self.scalenum = 1 # 缩放系数
# self.scaleflag = 0 # 放大还是缩小(0:不动,1:放大,-1:缩小)
self.nposx = 0 # 视图移动参数x
self.nposy = 0 # 视图移动参数y
# self.mindex = 1 # 当前区域编号
self.flag = 0 # 是否进行选点的flag
self.linkflag = 0 # 是否进行联动
def SetLinkFlag(self, flag):
"""设置是否联动"""
self.linkflag = flag
def SetLinkWidget(self, mwidget):
self.linkwidget = mwidget
def SetLinkPara(self, para):
"""设置联动参数并作出联动操作"""
scalenum = para[0]
# print(scaleflag)
nposx = para[1]
nposy = para[2]
# 设置缩放
if scalenum > self.scalenum:
self.scale(1.3, 1.3)
self.scalenum = self.scalenum*1.3
# self.scalflag = 1
elif scalenum < self.scalenum:
self.scale(1/1.3, 1/1.3)
self.scalenum = self.scalenum/1.3
# self.scalflag = -1
# 设置移动
if nposx != self.nposx and nposy != self.nposy:
self.horizontalScrollBar().setValue(nposx)
self.verticalScrollBar().setValue(nposy)
self.nposx = nposx
self.nposy = nposy
def GetLinkPara(self):
"""获取联动参数"""
para = []
para.append(self.scalenum)
para.append(self.nposx)
para.append(self.nposy)
return para
def InitializeView(self):
"""View初始化"""
self.points.clear()
self.allpoints.clear()
self.flag = 0
self.scalenum = 1
self.setCursor(qc.Qt.ArrowCursor)
def SetChoosePoint(self, flag):
"""设置是否选点"""
self.flag = flag
if flag == 0:
self.setCursor(qc.Qt.ArrowCursor)
if flag == 1 or flag == 2:
self.setCursor(qc.Qt.CrossCursor)
def GetFlag(self):
"""获取当前是在做什么"""
return self.flag
def GetPoints(self):
"""获取点集"""
return self.points
def ClearPoints(self):
"""删除点集"""
self.points.clear()
def GetAllPoints(self):
"""获取所有区域点集"""
return self.allpoints
def ClearPoints(self):
"""删除所有区域点集合"""
self.allpoints.clear()
def PersentLiner(self, data, ratio):
mdata = data.copy()
rows, cols = data.shape[0:2]
counts = rows*cols
mdata = mdata.reshape(counts, 1)
tdata = np.sort(mdata, axis=0)
cutmin = tdata[int(counts*ratio), 0]
cutmax = tdata[int(counts*(1-ratio)), 0]
ndata = 255.0*(data.astype(np.float32) - cutmin)/float(cutmax-cutmin)
ndata[data < cutmin] = 0
ndata[data > cutmax] = 255
return ndata
def SetImage(self, data):
"""设置影像"""
# if (data.type() == )
dtp = data.dtype
rows, cols, depth = data.shape
# 如果通道数大于3个,只保留前边三个通道
if depth > 3:
img = data[:, :, 0:3].copy()
img = img[:, :, ::-1]
else:
img = data.copy()
rows, cols, depth = img.shape
# 如果不是uint8的数据,需要先拉伸
if dtp != np.uint8:
for i in range(depth):
img[:,:,i] = self.PersentLiner(img[:,:,i].copy(), 0.02)
img = img.astype(np.uint8)
# numpy矩阵转换成QImage
if depth == 3:
nimg = qg.QImage(img.data, cols, rows, cols*depth,\
qg.QImage.Format_RGB888)
elif depth == 2:
b1 = np.float32(img[:, :, 0])
b2 = np.float32(img[:, :, 1])
img = np.uint8((b1+b2)/2.)
nimg = qg.QImage(img.data, cols, rows, cols*depth,\
qg.QImage.Format_Grayscale8)
elif depth == 1:
nimg = qg.QImage(img.data, cols, rows, cols*depth,\
qg.QImage.Format_Grayscale8)
pix = qg.QPixmap.fromImage(nimg)
item = qw.QGraphicsPixmapItem(pix)
showscene = qw.QGraphicsScene()
showscene.addItem(item)
self.setScene(showscene)
self.setTransform(qg.QTransform())
def wheelEvent(self, event):
if (event.angleDelta().y() > 0.5):
self.scale(1.3, 1.3)
self.scalenum = self.scalenum * 1.3
# self.scaleflag = 1
elif (event.angleDelta().y() < 0.5):
self.scale(1/1.3, 1/1.3)
# self.scaleflag = -1
self.scalenum = self.scalenum / 1.3
if self.linkflag == 1:
self.linkwidget.SetLinkPara(self.GetLinkPara())
def mousePressEvent(self, event):
button = event.button()
modifier = event.modifiers()
# 按住ctrl时变更鼠标样式
if button == qc.Qt.MiddleButton:
self.setCursor(qc.Qt.PointingHandCursor)
self.startpos = self.mapToScene(event.pos())
# print(self.startpos)
# 鼠标左键进行选点
elif button == qc.Qt.LeftButton and self.flag == 1:
p = self.mapToScene(event.pos())
self.points.append([p.x(), p.y()])
# 画点
pen = qg.QPen()
pen.setColor(qg.QColor(255, 0, 0))
pen.setWidth(2)
self.scene().addEllipse(p.x()-1, p.y()-1, 2, 2, pen)
num = len(self.points)
# 画线
if num>=2:
pen.setColor(qg.QColor(241, 89, 42))
pen.setWidth(1)
self.scene().addLine(self.points[num-2][0], \
self.points[num-2][1], \
self.points[num-1][0], \
self.points[num-1][1], pen)
# 鼠标左键只选点
elif button == qc.Qt.LeftButton and self.flag == 2:
p = self.mapToScene(event.pos())
self.points.append([p.x(), p.y()])
# 画点
pen = qg.QPen()
pen.setColor(qg.QColor(255, 0, 0))
pen.setWidth(2)
self.scene().addEllipse(p.x()-1, p.y()-1, 4, 4, pen)
# 添加文本
font = qg.QFont("Roman times", 20, qg.QFont.Bold)
text = qw.QGraphicsTextItem(str(len(self.points)))
text.setPos(p.x()-10, p.y()-10)
text.setDefaultTextColor(qg.QColor(248, 201, 0))
text.setFont(font)
self.scene().addItem(text)
# 鼠标右键完成当前区域选点
elif button == qc.Qt.RightButton and self.flag == 1:
self.allpoints.append(copy.deepcopy(self.points))
# 画线
pen = qg.QPen()
pen.setColor(qg.QColor(241, 89, 42))
pen.setWidth(1)
self.scene().addLine(self.points[-1][0], \
self.points[-1][1], \
self.points[0][0], \
self.points[0][1], pen)
# 添加文本
tps = np.array(self.points)
mps = np.mean(tps, axis=0)
font = qg.QFont("Roman times", 20, qg.QFont.Bold)
text = qw.QGraphicsTextItem(str(len(self.allpoints)))
text.setPos(mps[0]-20, mps[1]-20)
text.setDefaultTextColor(qg.QColor(248, 201, 0))
text.setFont(font)
self.scene().addItem(text)
# 这个区域点压入集合
self.points.clear()
def mouseReleaseEvent(self, event):
button = event.button()
modifier = event.modifiers()
# 鼠标中键弹起时进行视图移动
if button == qc.Qt.MiddleButton:
# 变更鼠标样式
if self.flag == 0:
self.setCursor(qc.Qt.ArrowCursor)
elif self.flag == 1 or self.flag == 2:
self.setCursor(qc.Qt.CrossCursor)
# 记录当前点进行视图移动
self.endpos = self.mapToScene(event.pos())
# 获取滚动条当前位置
oposx = self.horizontalScrollBar().value()
oposy = self.verticalScrollBar().value()
# 计算鼠标移动的距离
offset = self.endpos - self.startpos
# 根据移动的距离计算新的滚轮位置
nposx = oposx - offset.x()*self.scalenum
nposy = oposy - offset.y()*self.scalenum
# 设置新的滚轮位置
self.horizontalScrollBar().setValue(nposx)
self.verticalScrollBar().setValue(nposy)
# 记录一下备用
self.nposx = nposx
self.nposy = nposy
# 进行联动
if self.linkflag == 1:
self.linkwidget.SetLinkPara(self.GetLinkPara())
(2)再新建一个python脚本,新建一个QgraphicsViewTestGUI类,继承QWidget类,代码如下:
# yangzhen
# 2021.12.04
from PyQt5 import QtCore, QtGui, QtWidgets
import ImageShow
import numpy as np
import qimage2ndarray
class QgraphicsViewTestGUI(QtWidgets.QWidget):
def __init__(self):
super(QgraphicsViewTestGUI, self).__init__()
self.showMaximized()
# 设置主布局为格网布局
self.gridLayout = QtWidgets.QGridLayout(self)
self.gridLayout.setObjectName("gridLayout")
# 日志输出窗口与两个影像窗口为垂直分割布局
self.splitter = QtWidgets.QSplitter(self)
self.splitter.setOrientation(QtCore.Qt.Vertical)
self.splitter.setObjectName("splitter")
# 为两个影像显示窗口设置布局
self.layoutWidget = QtWidgets.QWidget(self.splitter)
self.layoutWidget.setObjectName("layoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
# 左影像显示窗口
self.graphicsView_LeftImage = ImageShow.MyQGraphicsView(self.layoutWidget)
self.graphicsView_LeftImage.setObjectName("graphicsView_LeftImage")
self.horizontalLayout.addWidget(self.graphicsView_LeftImage)
# 右影像显示窗口
self.graphicsView_RightImage = ImageShow.MyQGraphicsView(self.layoutWidget)
self.graphicsView_RightImage.setObjectName("graphicsView_RightImage")
self.horizontalLayout.addWidget(self.graphicsView_RightImage)
# 日志输出窗口
self.textBrowser_log = QtWidgets.QTextBrowser(self.splitter)
self.textBrowser_log.setStyleSheet("QTextBrowser\n"
"{\n"
" background:white;\n"
" font-size:20px;\n"
" font-family:微软雅黑;\n"
" font-weight:bold;\n"
"}")
self.textBrowser_log.setObjectName("textBrowser_log")
self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
# 初始化窗口
self.Initialize()
def Initialize(self):
"""窗口初始化用于影像显示的测试"""
# 设置事件过滤,用于选点测试
self.graphicsView_LeftImage.viewport().installEventFilter(self)
self.graphicsView_RightImage.viewport().installEventFilter(self)
# 设置窗口比例
self.splitter.setStretchFactor(0, 4)
self.splitter.setStretchFactor(1, 1)
# 设置联动
self.graphicsView_LeftImage.SetLinkFlag(1)
self.graphicsView_RightImage.SetLinkFlag(1)
self.graphicsView_LeftImage.SetLinkWidget(self.graphicsView_RightImage)
self.graphicsView_RightImage.SetLinkWidget(self.graphicsView_LeftImage)
# 显示图片
img1 = QtGui.QImage('E:/smallthings/temp/QgraphicsViewTestGUI/testimg.jpg')
img2 = QtGui.QImage('E:/smallthings/temp/QgraphicsViewTestGUI/testimg.jpg')
img1 = qimage2ndarray.rgb_view(img1)
img2 = qimage2ndarray.rgb_view(img2)
self.graphicsView_LeftImage.SetImage(img1)
self.graphicsView_RightImage.SetImage(img2)
# 设置选点
self.graphicsView_LeftImage.SetChoosePoint(2)
self.graphicsView_RightImage.SetChoosePoint(1)
def eventFilter(self, watched, event):
"""重写eventfilter事件"""
if event.type() == QtCore.QEvent.MouseButtonPress:
if event.button() == QtCore.Qt.LeftButton and watched == self.graphicsView_LeftImage.viewport():
ps = self.graphicsView_LeftImage.GetPoints()
if len(ps) != 0:
nowp = ps[-1]
self.ShowMsg("影像选点测试,影像上一个点第" +
str(len(ps)) +
"个点,坐标为:(" +
str('%.3f'%nowp[0]) + ", " +
str('%.3f'%nowp[1]) + ")")
elif event.button() == QtCore.Qt.RightButton and watched == self.graphicsView_RightImage.viewport():
areas = self.graphicsView_RightImage.GetAllPoints()
if len(areas) != 0:
nowarea = areas[-1]
coorstr = ''
for coor in nowarea:
tstr = "(" + str('%.3f'%coor[0]) + ", " + str('%.3f'%coor[1]) + ")\n"
coorstr += tstr
self.ShowMsg("影像选区域测试,影像上一个区域第" +
str(len(areas)) +
"个区域,坐标集为:\n" + coorstr)
return QtWidgets.QWidget.eventFilter(self, watched, event)
def ShowMsg(self, msg):
"""追加的方式在ttextBrowser_log上写东西,为了日志的显示"""
self.textBrowser_log.moveCursor(QtGui.QTextCursor.End)
self.textBrowser_log.append('>>' + msg)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
ui = QgraphicsViewTestGUI()
ui.show()
sys.exit(app.exec_())
(3)然后就可以愉快的运行了
后记:
两个版本的源代码也是有的: