Pyside2:我正在对QGraphicsView进行子类化,并为mouseClickEvent和mouseMoveEvent添加缩放和平移功能。
执行此操作时,场景中启用了"可选择"one_answers"可移动"的QGraphicsItems在第一次单击并拖动后不会正确移动。
它们在第一次点击和拖动时移动得很好,但如果我再次点击和拖动它们,它们会弹回到创建位置并从那里移动。
这是我所拥有的:
class ZoomView(QGraphicsView):
'''
View class with zoom enabled
'''
def __init__(self):
super(ZoomView, self).__init__()
self.alt_key = False
self.ctrl_key = False
self.mid_button = False
self.left_button = False
self.mouse_pos = None
self.orig_pos = None
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(2)
sizePolicy.setHeightForWidth(True)
self.setSizePolicy(sizePolicy)
self.setMinimumSize(QtCore.QSize(0, 0))
self.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing)
self.setResizeAnchor(QGraphicsView.NoAnchor)
self.setObjectName("PickerView")
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Alt:
self.alt_key = True
elif event.key() == QtCore.Qt.Key_Control:
self.ctrl_key = True
else:
return super(ZoomView, self).keyPressEvent(event)
def keyReleaseEvent(self, event):
if event.key() == QtCore.Qt.Key_Alt:
self.alt_key = False
elif event.key() == QtCore.Qt.Key_Control:
self.ctrl_key = False
else:
return super(ZoomView, self).keyReleaseEvent(event)
def mousePressEvent(self, event):
self.mouse_pos = event.pos()
if event.button() == QtCore.Qt.MidButton:
self.mid_button = True
if event.button() == QtCore.Qt.LeftButton:
super(ZoomView, self).mousePressEvent(event)
self.left_button = True
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.MidButton:
self.mid_button = False
elif event.button() == QtCore.Qt.LeftButton:
self.left_button = False
else:
return super(ZoomView, self).mouseReleaseEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() == QtCore.Qt.NoButton:
return super(ZoomView, self).mouseMoveEvent(event)
new_pos = event.pos()
diff_x = self.mouse_pos.x() - new_pos.x()
diff_y = self.mouse_pos.y() - new_pos.y()
if self.alt_key and self.mid_button and not self.left_button:
# pan the screen
h_scroll = self.horizontalScrollBar()
v_scroll = self.verticalScrollBar()
H_scrollFinal = h_scroll.value() + diff_x
V_scrollFinal = v_scroll.value() + diff_y
h_scroll.setValue(H_scrollFinal)
v_scroll.setValue(V_scrollFinal)
self.mouse_pos = new_pos
elif self.alt_key and self.left_button and self.mid_button:
# zoom
actualScale = self.transform().m11()
coefDdiff_x = diff_x * 0.004
scaleFactor = actualScale - coefDdiff_x
if scaleFactor > 0.05 and scaleFactor < 3:
matrice = QtGui.QTransform(scaleFactor, 0, 0, 0, scaleFactor, 0, 0, 0, 1)
self.setTransform(matrice, combine=False)
h_scroll = self.horizontalScrollBar()
v_scroll = self.verticalScrollBar()
self.mouse_pos = new_pos
else:
return super(ZoomView, self).mouseMoveEvent(event)
Ok找到了解决方案。
当您将QGraphicsView子类化并覆盖这些鼠标方法时
mousePressEvent()
mouseMoveEvent()
mouseReleaseEvent()
在运行自定义缩放/平移代码之前,您需要在每个方法的开头放一个"if"语句,检查鼠标是否在其中一个项目上。如果鼠标在像rect或椭圆这样的项上,那么只需运行该方法的super并返回。此外,如果选择了矩形或椭圆,则运行super并返回。
这里有一个例子:
class MyView(QGraphicsView):
def mousePressEvent(self, event):
# check if clicking on a button first or if a button is selected
scene = self.scene()
items = scene.items(event.localPos())
if self.selected_items():
super(Picker_View, self).mousePressEvent(event)
return
if items and isinstance(items[0], Ellipse_Button):
# QGraphicsScene.mousePressEvent(self, event)
super(Picker_View, self).mousePressEvent(event)
return
self.foo()
def selected_items(self):
'''
Checks if any items in the graphics scene are selected
Returns:
(boolean)
'''
scene = self.scene()
elements = scene.items()
for element in elements:
if element.isSelected():
return True
else:
pass
return False