gpt4 book ai didi

qt - QGraphicsView 双击事件和 ScrollHandDrag 模式项问题

转载 作者:行者123 更新时间:2023-12-04 10:24:21 28 4
gpt4 key购买 nike

我正在尝试创建一个具有以下行为的 QGraphicsView:

  • 当按住 control 键并按下鼠标左键时,应将 View 设置为 ScrollHandDrag 模式以允许用户平移。
  • 在 ScrollHandDrag 模式下,项目不应该是可选/可移动的,如这里的问题:In ScrollHandDrag mode of QGraphicsView, How to stop movement of QGraphicsItems on scene?
  • 如果按住 control 键,单击鼠标左键,然后松开 control 键,则 View 应保持 ScrollHandDrag 模式直到释放鼠标,否则如果此时按下 control 键,则将保持此模式鼠标被释放。

  • 对我来说,这听起来应该相当简单。我已经实现了链接问题中的逻辑,以及一些额外的逻辑来满足我的额外要求。然而,这似乎导致以下两个showstoppers:
  • 在mousePressEvent中,将鼠标下的item设置为没有movable和selectable标志,调用基类,然后重新应用flags会导致item变成“卡住”。解决这个问题的唯一方法似乎是控制+单击,释放控制+在项目外单击几次。此外,当它进入此状态时,无法移动任何项目(尽管它们仍然可以被选中)。
  • 双击 View 会导致一个 mousePressEvent,然后是两个 mouseReleaseEvents!这打破了我的逻辑。

  • 所以我想知道如何解决 In ScrollHandDrag mode of QGraphicsView, How to stop movement of QGraphicsItems on scene? 的逻辑时项目卡住的问题使用,以及如何处理奇怪的双击鼠标事件 - 有没有办法关闭它们?

    这是我的代码(这几乎也是我的 hello world Python,所以如果我犯了一些可怕的 Python 错误,请告诉我):
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-

    import sys
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *

    class MyMainWindow(QMainWindow):
    def __init__(self):
    super(MyMainWindow, self).__init__()
    self.initUI()

    def initUI(self):
    self.setWindowTitle("Test")
    self.gv = MyGraphicsView()
    self.setCentralWidget(self.gv)
    self.setGeometry(170, 130, 450, 250)

    class MyGraphicsView(QGraphicsView):
    def __init__(self):
    super(MyGraphicsView, self).__init__()
    self.setup()

    def setup(self):
    self.m_MouseIsDown = False
    self.m_ControlKeyDown = False
    self.setDragMode(QGraphicsView.RubberBandDrag)

    def mouseMoveEvent(self, event):
    # print "mouseMoveEvent: " + str(event.pos().x()) + "," + str(event.pos().y())
    super(MyGraphicsView, self).mouseMoveEvent(event);

    def mousePressEvent(self, event):
    print "mousePressEvent"

    itemUnderMouse = self.itemAt(event.pos())
    if itemUnderMouse is not None:
    bHadMovableFlagSet = itemUnderMouse.flags() & QGraphicsItem.ItemIsMovable
    bWasSelected = itemUnderMouse.isSelected()
    bHadSelectableFlagSet = itemUnderMouse.flags() & QGraphicsItem.ItemIsSelectable
    if bHadMovableFlagSet:
    print "has ItemIsMovable"
    else:
    print "hasn't ItemIsMovable"
    if bHadSelectableFlagSet:
    print "has ItemIsSelectable"
    else:
    print "hasn't ItemIsSelectable"
    if bWasSelected:
    print "isSelected true"
    else:
    print "isSelected false"
    itemUnderMouse.setSelected(False)

    if event.button() == Qt.LeftButton:
    print "mousePressEvent: left button is now down"
    self.m_MouseIsDown = True

    if self.dragMode() == QGraphicsView.ScrollHandDrag and event.button() == Qt.LeftButton:
    print "mousePressEvent: left button down and ScrollHandDrag set"
    self.PreventItemsFromMovingOrBeingSelectedWhenPannning(event)
    return

    print "mousePressEvent: pass through"
    super(MyGraphicsView, self).mousePressEvent(event)

    def mouseReleaseEvent(self, event):
    print "mouseReleaseEvent"
    if event.button() == Qt.LeftButton:
    print "mouseReleaseEvent - left button is now up"
    self.m_MouseIsDown = False
    if self.dragMode() == QGraphicsView.ScrollHandDrag and self.m_ControlKeyDown == False:
    print "mouseReleaseEvent - left button up, in ScrollHandDrag mode and control key is not pressed, change to RubberBandDrag"
    self.setDragMode(QGraphicsView.RubberBandDrag)

    super(MyGraphicsView, self).mouseReleaseEvent(event)

    def keyPressEvent(self, event):
    if event.key() == Qt.Key_Control:
    print "control key down"
    self.m_ControlKeyDown = True

    # ignore if mouse already down since we don't want to suddenly change to pan mode if an item is being moved
    if event.key() == Qt.Key_Control and self.dragMode() != QGraphicsView.ScrollHandDrag and self.m_MouseIsDown == False:
    print "keyPressEvent - control key down, mouse isn't down and drag mode is not ScrollHandDrag, change to ScrollHandDrag"
    self.setDragMode(QGraphicsView.ScrollHandDrag)
    super(MyGraphicsView, self).keyPressEvent(event)

    def keyReleaseEvent(self, event):
    if event.key() == Qt.Key_Control:
    print "control key up"
    self.m_ControlKeyDown = False

    if event.key() == Qt.Key_Control and self.dragMode() == QGraphicsView.ScrollHandDrag and self.m_MouseIsDown == False:
    print "keyReleaseEvent - control key up and drag mode is ScrollHandDrag, mouse is not pressed, change to RubberBandDrag"
    self.setDragMode(QGraphicsView.RubberBandDrag)
    super(MyGraphicsView, self).keyReleaseEvent(event)

    def wheelEvent(self, event):
    factor = 1.2;
    if event.delta() < 0:
    factor = 1.0 / factor
    self.scale(factor, factor)

    def PreventItemsFromMovingOrBeingSelectedWhenPannning(self, mouseEvent):
    itemUnderMouse = self.itemAt(mouseEvent.pos())
    if itemUnderMouse is not None:
    print "preventing item from moving"
    bHadMovableFlagSet = itemUnderMouse.flags() & QGraphicsItem.ItemIsMovable
    itemUnderMouse.setFlag(QGraphicsItem.ItemIsMovable, False)

    bWasSelected = itemUnderMouse.isSelected()

    bHadSelectableFlagSet = itemUnderMouse.flags() & QGraphicsItem.ItemIsSelectable
    itemUnderMouse.setFlag(QGraphicsItem.ItemIsSelectable, False)

    super(MyGraphicsView, self).mousePressEvent(mouseEvent)

    if bHadMovableFlagSet:
    print "set ItemIsMovable"
    itemUnderMouse.setFlag(QGraphicsItem.ItemIsMovable, True)
    if bHadSelectableFlagSet:
    print "set ItemIsSelectable"
    itemUnderMouse.setFlag(QGraphicsItem.ItemIsSelectable, True)
    if bWasSelected:
    print "setSelected True"
    itemUnderMouse.setSelected(True)

    else:
    print "no item under mouse - pass through"
    super(MyGraphicsView, self).mousePressEvent(mouseEvent)

    class MyGraphicsScene(QGraphicsScene):
    def __init__(self, parent):
    super(MyGraphicsScene, self).__init__()

    def main():
    a = QApplication(sys.argv)
    w = MyMainWindow()
    w.show()

    scene = MyGraphicsScene(w)
    w.gv.setScene(scene)

    rect = scene.addRect( 10, 10, 40, 40)
    rect.setFlag( QGraphicsItem.ItemIsSelectable )
    rect.setFlag( QGraphicsItem.ItemIsMovable )

    rect = scene.addRect( 40, 40, 40, 40)
    rect.setFlag( QGraphicsItem.ItemIsSelectable )
    rect.setFlag( QGraphicsItem.ItemIsMovable )

    sys.exit(a.exec_())

    if __name__ == '__main__':
    main()

    最佳答案

    如果您不在 mouse*Event 中调用基本实现s 在平移时,项目选择不会成为问题。但是,这现在需要重新实现内置的平移功能。幸运的是,实现它并不难。

    在 IRC (#pyqt @ freenode) 进行一些迭代后,这是最终实现:

  • 按住 CTRL 键可启用平移。按下鼠标时,释放 CTRL 键保持平移模式。
  • 只需按下鼠标即可激活橡胶选择
  • 所有 Action 都由左按钮控制

  • class MyGraphicsView(QGraphicsView):
    def __init__(self):
    super(MyGraphicsView, self).__init__()
    self.setDragMode(QGraphicsView.RubberBandDrag)
    self._isPanning = False
    self._mousePressed = False

    def mousePressEvent(self, event):
    if event.button() == Qt.LeftButton:
    self._mousePressed = True
    if self._isPanning:
    self.setCursor(Qt.ClosedHandCursor)
    self._dragPos = event.pos()
    event.accept()
    else:
    super(MyGraphicsView, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
    if self._mousePressed and self._isPanning:
    newPos = event.pos()
    diff = newPos - self._dragPos
    self._dragPos = newPos
    self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - diff.x())
    self.verticalScrollBar().setValue(self.verticalScrollBar().value() - diff.y())
    event.accept()
    else:
    super(MyGraphicsView, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
    if event.button() == Qt.LeftButton:
    if event.modifiers() & Qt.ControlModifier:
    self.setCursor(Qt.OpenHandCursor)
    else:
    self._isPanning = False
    self.setCursor(Qt.ArrowCursor)
    self._mousePressed = False
    super(MyGraphicsView, self).mouseReleaseEvent(event)

    def mouseDoubleClickEvent(self, event): pass

    def keyPressEvent(self, event):
    if event.key() == Qt.Key_Control and not self._mousePressed:
    self._isPanning = True
    self.setCursor(Qt.OpenHandCursor)
    else:
    super(MyGraphicsView, self).keyPressEvent(event)

    def keyReleaseEvent(self, event):
    if event.key() == Qt.Key_Control:
    if not self._mousePressed:
    self._isPanning = False
    self.setCursor(Qt.ArrowCursor)
    else:
    super(MyGraphicsView, self).keyPressEvent(event)


    def wheelEvent(self, event):
    factor = 1.2;
    if event.delta() < 0:
    factor = 1.0 / factor
    self.scale(factor, factor)

    关于qt - QGraphicsView 双击事件和 ScrollHandDrag 模式项问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15034627/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com