Python 尝试在pyqt5中的鼠标事件之间切换

Python 尝试在pyqt5中的鼠标事件之间切换,python,pyqt5,mouseevent,Python,Pyqt5,Mouseevent,我正在尝试制作一个gui,用户可以在拖动模式下移动图像,然后切换到绘图模式,在qgraphicsview中绘制图像。我有我找到的示例中的代码,但我不知道如何在两个鼠标事件之间切换。我还在努力研究如何链接两个qgraphicsview对象,以便在这两个对象之间共享拖动和缩放事件。下面是我的代码,如果有任何不合理的地方,请尽管问。提前谢谢 from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt, QPoint fr

我正在尝试制作一个gui,用户可以在拖动模式下移动图像,然后切换到绘图模式,在qgraphicsview中绘制图像。我有我找到的示例中的代码,但我不知道如何在两个鼠标事件之间切换。我还在努力研究如何链接两个qgraphicsview对象,以便在这两个对象之间共享拖动和缩放事件。下面是我的代码,如果有任何不合理的地方,请尽管问。提前谢谢

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,在两个视图上应用相同的变换,然后再次取消滚动条的阻塞信号。

谢谢,我现在可以使用绘图功能了。