Python 尝试在pyqt5中的鼠标事件之间切换
我正在尝试制作一个gui,用户可以在拖动模式下移动图像,然后切换到绘图模式,在qgraphicsview中绘制图像。我有我找到的示例中的代码,但我不知道如何在两个鼠标事件之间切换。我还在努力研究如何链接两个qgraphicsview对象,以便在这两个对象之间共享拖动和缩放事件。下面是我的代码,如果有任何不合理的地方,请尽管问。提前谢谢Python 尝试在pyqt5中的鼠标事件之间切换,python,pyqt5,mouseevent,Python,Pyqt5,Mouseevent,我正在尝试制作一个gui,用户可以在拖动模式下移动图像,然后切换到绘图模式,在qgraphicsview中绘制图像。我有我找到的示例中的代码,但我不知道如何在两个鼠标事件之间切换。我还在努力研究如何链接两个qgraphicsview对象,以便在这两个对象之间共享拖动和缩放事件。下面是我的代码,如果有任何不合理的地方,请尽管问。提前谢谢 from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt, QPoint fr
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtGui import QPixmap, QPainter, QPen
import sys
class PhotoViewer(QtWidgets.QGraphicsView):
photoClicked = QtCore.pyqtSignal(QtCore.QPoint)
def __init__(self, parent):
super(PhotoViewer, self).__init__(parent)
self.drawmode=0
self._zoom = 0
self.drawing = False
self.lastPoint = QPoint()
self.image=False
self.image=QPixmap(r"image.jpg")
self._empty = True
self._scene = QtWidgets.QGraphicsScene(self)
self._photo = QtWidgets.QGraphicsPixmapItem()
self._scene.addItem(self._photo)
self.setScene(self._scene)
self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(30, 30, 30)))
self.setFrameShape(QtWidgets.QFrame.NoFrame)
def hasPhoto(self):
return not self._empty
def fitInView(self, scale=True):
rect = QtCore.QRectF(self._photo.pixmap().rect())
if not rect.isNull():
self.setSceneRect(rect)
if self.hasPhoto():
unity = self.transform().mapRect(QtCore.QRectF(0, 0, 1, 1))
self.scale(1 / unity.width(), 1 / unity.height())
viewrect = self.viewport().rect()
scenerect = self.transform().mapRect(rect)
factor = min(viewrect.width() / scenerect.width(),
viewrect.height() / scenerect.height())
self.scale(factor, factor)
self._zoom = 0
def setPhoto(self, pixmap=None):
self._zoom = 0
if pixmap and not pixmap.isNull():
self._empty = False
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self._photo.setPixmap(pixmap)
else:
self._empty = True
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
self._photo.setPixmap(QtGui.QPixmap())
self.fitInView()
def wheelEvent(self, event):
if self.hasPhoto():
if event.angleDelta().y() > 0:
factor = 1.25
self._zoom += 1
else:
factor = 0.8
self._zoom -= 1
if self._zoom > 0:
self.scale(factor, factor)
elif self._zoom == 0:
self.fitInView()
else:
self._zoom = 0
def toggleDragMode(self):
if self.dragMode() == QtWidgets.QGraphicsView.ScrollHandDrag:
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
elif not self._photo.pixmap().isNull():
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
#drawing events that im trying to add
# def paintEvent(self, event):
# painter = QPainter(self)
# painter.drawPixmap(self.rect(), self.image)
#
# def mousePressEvent(self, event):
# if event.button() == Qt.LeftButton:
# self.drawing = True
# self.lastPoint = event.pos()
#
# def mouseMoveEvent(self, event):
# if event.buttons() and Qt.LeftButton and self.drawing:
# painter = QPainter(self.image)
# painter.setPen(QPen(Qt.blue, 7, Qt.SolidLine))
# painter.drawLine(self.lastPoint, event.pos())
# self.lastPoint = event.pos()
# self.update()
#
# def mouseReleaseEvent(self, event):
# if event.button == Qt.LeftButton:
# self.drawing = False
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.viewer = PhotoViewer(self)
self.viewer2 = PhotoViewer(self)
# 'Load image' button
self.btnLoad = QtWidgets.QToolButton(self)
self.btnLoad.setText('Load image')
self.btnLoad.clicked.connect(self.loadImage)
# draw mode
self.btndraw = QtWidgets.QToolButton(self)
self.btndraw.setText('Draw Mode')
self.btndraw.clicked.connect(self.drawmode)
# Button to change from drag/pan to getting pixel info
self.btnPixInfo = QtWidgets.QToolButton(self)
self.btnPixInfo.setText('Enter pixel info mode')
self.btnPixInfo.clicked.connect(self.pixInfo)
self.editPixInfo = QtWidgets.QLineEdit(self)
self.editPixInfo.setReadOnly(True)
self.viewer.photoClicked.connect(self.photoClicked)
# Arrange layout
VBlayout = QtWidgets.QVBoxLayout(self)
HBlayout2 = QtWidgets.QHBoxLayout()
HBlayout2.setAlignment(QtCore.Qt.AlignLeft)
HBlayout2.addWidget(self.viewer2)
HBlayout2.addWidget(self.viewer)
HBlayout = QtWidgets.QHBoxLayout()
HBlayout.setAlignment(QtCore.Qt.AlignLeft)
HBlayout.addWidget(self.btnLoad)
HBlayout.addWidget(self.btnPixInfo)
HBlayout.addWidget(self.btndraw)
HBlayout.addWidget(self.editPixInfo)
VBlayout.addLayout(HBlayout2)
VBlayout.addLayout(HBlayout)
def loadImage(self):
self.viewer.setPhoto(QtGui.QPixmap(r'image.jpg'))
self.viewer2.setPhoto(QtGui.QPixmap(r'image.jpg'))
self.image=QPixmap(r"image.jpg")
def drawmode(self):
self.viewer.toggleDrawMode()
def pixInfo(self):
self.viewer.toggleDragMode()
def photoClicked(self, pos):
if self.viewer.dragMode() == QtWidgets.QGraphicsView.NoDrag:
self.editPixInfo.setText('%d, %d' % (pos.x(), pos.y()))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 800, 600)
window.show()
sys.exit(app.exec_())
def drawmode中有一个输入错误,它调用toggleDrawMode而不是toggleDragMode。除此之外,最好避免在视图上绘制,除非您真的需要并知道自己在做什么,或者在移动鼠标时直接在图像上绘制,更好的方法可能是在按下鼠标时添加QGraphicsPathItem,并在释放鼠标按钮后在图像上实际绘制:
def mousePressEvent(self, event):
if (event.button() == Qt.LeftButton and not self._photo.pixmap().isNull()
and self.dragMode() == QtWidgets.QGraphicsView.NoDrag):
self.drawingPath = QtGui.QPainterPath()
self.drawingPath.moveTo(self.mapToScene(event.pos()))
self.drawingItem = self.scene().addPath(self.drawingPath)
self.drawingItem.setPen(QtGui.QPen(Qt.blue, 7, Qt.SolidLine))
else:
super(PhotoViewer, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() and Qt.LeftButton and self.drawingPath:
self.drawingPath.lineTo(self.mapToScene(event.pos()))
self.drawingItem.setPath(self.drawingPath)
else:
super(PhotoViewer, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton and self.drawingPath:
pm = self._photo.pixmap()
painter = QtGui.QPainter(pm)
painter.setPen(QPen(Qt.red, 7, Qt.SolidLine))
painter.drawPath(self.drawingPath)
painter.end()
self._photo.setPixmap(pm)
self.scene().removeItem(self.drawingItem)
self.drawingPath = None
else:
super(PhotoViewer, self).mouseReleaseEvent(event)
关于两个视图的链接,如果拖动指的是视图滚动,则只需将两个相对滚动条valueChanged与另一个上的setValue链接,并且记住,无论何时要应用变换,都必须对所有4个滚动条应用blockSignalsTrue,在两个视图上应用相同的变换,然后再次取消滚动条的阻塞信号。谢谢,我现在可以使用绘图功能了。