我想将Python-Qt QGraphicsView对象子类化以显示一些图像,我希望能够通过鼠标拖动进行平移。但是,方法QGraphicsView.translate(x,y)
和QGraphicsView.CenterOn(x,y)
不起作用。这是一个简单的示例代码片段(为简单起见,我遗漏了mouseMoveEvent
):
import sys
from qtpy import QtGui, QtCore, QtWidgets
class MyView(QtWidgets.QGraphicsView):
def __init__(self):
QtWidgets.QGraphicsView.__init__(self)
self.scene = QtWidgets.QGraphicsScene(self)
self.item = QtWidgets.QGraphicsEllipseItem(-20, -10, 160, 160)
self.scene.addItem(self.item)
self.setScene(self.scene)
self._drag = False
self._pos = QtCore.QPointF(0.0, 0.0)
def wheelEvent(self, event):
if event.angleDelta().y() > 0:
self.scale(1.5,1.5) # Increase zoom
else:
self.scale(0.75,0.75) # Decrease zoom
def mousePressEvent(self, event):
self._drag = True
self._pos = event.pos()
def mouseReleaseEvent(self, event):
if self._drag:
self._drag = False
newPos = event.pos()
delta = self._pos - newPos
# What the docs say work to translate:
self.translate( delta.x(), delta.y() )
aff = self.transform()
print( 'isTranslating: {}, dx: {}, dy: {}'.format(aff.isTranslating(), aff.dx(), aff.dy()) )
print( 'hozScroll: {}, vertScroll: {}'.format( self.horizontalScrollBar().value(), self.verticalScrollBar().value() ) )
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
view = MyView()
view.show()
sys.exit(app.exec_())
如果需要,将PySide2
或PyQt5
替换为qtpy
。要启用翻译,首先必须使用鼠标滚轮滚动。然后你尝试拖动你可以看到,虽然转换变换矩阵正在改变,但视图不会翻译。
答案 0 :(得分:1)
因为QGraphicsView:
http://pyside.github.io/docs/pyside/PySide/QtGui/QGraphicsView.html
是QAbstractScrollArea的子类:
http://pyside.github.io/docs/pyside/PySide/QtGui/QAbstractScrollArea.html
QGraphicsView.translate()
会移动场景,但随后会调用父类,并且连接到滚动条的信号会将场景移回滚动条指示的位置。一种解决方案是关闭滚动条信号:
self.setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff )
self.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff )
self.horizontalScrollBar().disconnect()
self.verticalScrollBar().disconnect()
如果要保留滚动条,则必须直接设置它们:
self.horizontalScrollBar().setValue( self.horizontalScrollBar().value() + delta.x() )
self.verticalScrollBar().setValue( self.verticalScrollBar().value() + delta.y() )
或者你可能会重新插入进入它们的信号/插槽。