简体   繁体   中英

Change ScrollHandDrag form left click to middle click PYQT5

I am curious if there is a way to change the QGraphicsView.ScrollHandDrag to work with the center button instead of the left mouse button for panning when the user is zoomed into the points. Also Is there a way to not have any bounds on where the user can pan too? Thank you for all your help. I have attached some code below.

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

from math import sqrt

class Point(QGraphicsItem):
    def __init__(self, x, y):
        super(Point, self).__init__()
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.rectF = QRectF(0, 0, 30, 30)
        self.x=x
        self.y=y
        self._brush = QBrush(Qt.black)

    def setBrush(self, brush):
        self._brush = brush
        self.update()

    def boundingRect(self):
        return self.rectF

    def paint(self, painter=None, style=None, widget=None):
        painter.fillRect(self.rectF, self._brush)

    def hoverMoveEvent(self, event):
        point = event.pos().toPoint()
        print(point)
        QGraphicsItem.hoverMoveEvent(self, event)


class PhotoViewer(QGraphicsView):
    photoClicked = pyqtSignal(QPoint)

    def __init__(self, parent):
        super(PhotoViewer, self).__init__(parent)
        self._zoom = 0
        self._empty = True
        self._scene = QGraphicsScene(self)

        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setFrameShape(QFrame.NoFrame)
        self.area = float()
        self.setPoints()

    def setItems(self):
            self.data = {'x': [-2414943.8686, -2417160.6592, -2417160.6592, -2417856.1783, -2417054.7618, -2416009.9966, -2416012.5232, -2418160.8952, -2418160.8952, -2416012.5232, -2417094.7694, -2417094.7694], 'y': [10454269.7008,
     10454147.2672, 10454147.2672, 10453285.2456, 10452556.8132, 10453240.2808, 10455255.8752, 10455183.1912, 10455183.1912, 10455255.8752, 10456212.5959, 10456212.5959]}
            maxX = max(self.data['x'])
            minX = min(self.data['x'])
            maxY = max(self.data['y'])
            minY = min(self.data['y'])
            distance = sqrt((maxX-minX)**2+(maxY-minY)**2)

            self.area = QRectF(minX, minY, distance, distance)
            for i,x in enumerate(self.data['x']):
                x = self.data['x'][i]
                y = self.data['y'][i]
                p = Point(x,y)
                p.setPos(x,y)
                self._scene.addItem(p)
            self.setScene(self._scene)



    def fitInView(self, scale=True):
        rect = QRectF(self.area)
        if not rect.isNull():
            self.setSceneRect(rect)

            unity = self.transform().mapRect(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 setPoints(self):
        self._zoom = 0
        self.setItems()
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        self.fitInView()

    def wheelEvent(self, event):
            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 mousePressEvent(self, event):
        if event.button() == Qt.MidButton:
            #Im Sure I have to do something here.
            pass
        super(PhotoViewer, self).mousePressEvent(event)


class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.viewer = PhotoViewer(self)
        # 'Load image' button
        self.btnLoad = QToolButton(self)
        self.btnLoad.setText('Load Points')
        self.btnLoad.clicked.connect(self.loadPoints)

        VBlayout = QVBoxLayout(self)
        VBlayout.addWidget(self.viewer)
        HBlayout = QHBoxLayout()
        HBlayout.setAlignment(Qt.AlignLeft)
        HBlayout.addWidget(self.btnLoad)

        VBlayout.addLayout(HBlayout)

    def loadPoints(self):
        self.viewer.setPoints()




if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 800, 600)
    window.show()
    sys.exit(app.exec_())

yes, you can change the pan cursor.

Please change the part of your code to these.

def mousePressEvent(self, event):

    if event.button() == Qt.MidButton:
        self.viewport().setCursor(Qt.ClosedHandCursor)  
        self.original_event = event
        handmade_event = QMouseEvent(QEvent.MouseButtonPress,QPointF(event.pos()),Qt.LeftButton,event.buttons(),Qt.KeyboardModifiers())
        self.mousePressEvent(handmade_event)
        #Im Sure I have to do something here.

    super(PhotoViewer, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
    if event.button() == Qt.MidButton:
        #for changing back to Qt.OpenHandCursor
        self.viewport().setCursor(Qt.OpenHandCursor)
        handmade_event = QMouseEvent(QEvent.MouseButtonRelease,QPointF(event.pos()),Qt.LeftButton,event.buttons(),Qt.KeyboardModifiers())
        self.mouseReleaseEvent(handmade_event)
    super(PhotoViewer, self).mouseReleaseEvent(event)

Explanation

For changing mousecursor picture on QGraphicsView ,basically,

QGraphicsView.vieport().setCursor()

Why can Qt.LeftButton change the cursor by default?

I think it is the default setting.Probably,the developper of Qt predicts the users want the screen to pan by pressing left-button , when the cursor shape is OpenHandCursor .

So,probably, you can't keep the cursor "open" on the case of LeftButton vice versa. It is embedded in super(PhotoViewer, self).mousePressEvent(event) We will not be able to connect the contents. So you don't want the change by LeftMouse, you write return and you write other command here.

Handmade Event Object

If you push MidButton , you make the LeftButton MouseEvent by yourself, and you pass it to the mousePressEvent. mousePressEvent accepts it, and it handles as if it were the leftButton event.

If you put the handmade code only in the mousePressEvent ,you will not be able to escape from the trap.So you also put the handmade code in the mouseReleaseEvent .

Perfect.It depends on what you write commands in the event handler. If you don't want leftButton to pan, you do the same thing in it. That is to say, you can switch the events between LeftButton and MidButton !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM