简体   繁体   English

将ScrollHandDrag表单的左键更改为中键PYQT5

[英]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. 我很好奇是否有一种方法可以将QGraphicsView.ScrollHandDrag更改为使用中心按钮而不是鼠标左键进行平移(当用户放大点时)。 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上更改mousecursor图片,基本上,

QGraphicsView.vieport().setCursor()

Why can Qt.LeftButton change the cursor by default? 为什么Qt.LeftButton默认可以更改光标?

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 . 我认为这是默认设置。当光标形状为OpenHandCursor时, Qt的开发人员可能会预测用户希望通过按左按钮来平移屏幕。

So,probably, you can't keep the cursor "open" on the case of LeftButton vice versa. 因此,在LeftButton的情况下,您可能无法使光标保持“打开”状态,反之亦然。 It is embedded in super(PhotoViewer, self).mousePressEvent(event) We will not be able to connect the contents. 它嵌入在super(PhotoViewer, self).mousePressEvent(event)我们将无法连接内容。 So you don't want the change by LeftMouse, you write return and you write other command here. 因此,您不希望通过LeftMouse进行更改,而是在此处编写return和其他命令。

Handmade Event Object 手工事件对象

If you push MidButton , you make the LeftButton MouseEvent by yourself, and you pass it to the mousePressEvent. 如果按下MidButton ,则可以自己制作LeftButton MouseEvent,并将其传递给mousePressEvent。 mousePressEvent accepts it, and it handles as if it were the leftButton event. mousePressEvent接受它,并且其处理方式就好像是leftButton事件一样。

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 . 如果仅将手工代码放入mousePressEvent ,则您将无法从陷阱中逃脱。因此,还将手工代码放入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. 如果您不想平移leftButton,则可以在其中执行相同的操作。 That is to say, you can switch the events between LeftButton and MidButton ! 也就是说,您可以在LeftButtonMidButton之间切换事件!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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