pau*_*ulm 4 qt qt4 pyqt pyqt4 python-2.7
我正在尝试使用以下行为创建QGraphicsView:
当按住控制键并且鼠标左键停止时,视图应设置为ScrollHandDrag模式以允许用户平移.
在ScrollHandDrag模式下,项目不应该是可选择/可移动的,如下面的问题所示:在QGraphicsView的ScrollHandDrag模式中,如何停止场景中QGraphicsItems的移动?
如果按住控制键,则单击鼠标左键,然后释放控制键,然后视图应保持ScrollHandDrag模式直到释放鼠标,或者如果控制键在此时停止,则将保持此模式鼠标被释放.
对我来说,这听起来应该是相当简单的.我已经从链接的问题中实现了逻辑,并为我的额外需求提供了一些额外的逻辑.然而,这似乎导致以下两个showstoppers:
在mousePressEvent中,将鼠标下的项设置为不具有可移动和可选择的标志,调用基类,然后重新应用标志会使项目变为"冻结".解决这个问题的唯一方法似乎是控件+点击,释放控制+释放在项目外单击几次.此外,当它进入此状态时,不能移动任何项目(尽管仍然可以选择它们).
双击视图会导致mousePressEvent,然后是两个mouseReleaseEvents!这打破了我的逻辑.
所以我想知道如何在QGraphicsView的In ScrollHandDrag模式中解决物品被冻结的问题,如何停止QGraphicsItems在场景中的移动?使用,以及如何处理奇怪的双击鼠标事件 - 是否有办法将其关闭?
这是我的代码(这也是我的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()
Run Code Online (Sandbox Code Playgroud)
如果mouse*Event在平移时没有调用s中的基本实现,则项目选择不会成为问题.但是,现在需要重新实现内置的平移功能.幸运的是,实现它并不困难.
在IRC(#pyqt @ freenode)进行一些迭代后,这是最终的实现:
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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4395 次 |
| 最近记录: |