我是按照这个帖子里的想法来的。
https:/stackoverflow.coma388608092407089。
其中QGraphicsSvgItem类中的hoverMoveEvent方法允许某人通过self.scenePos和self.setPos在场景周围拖动图像。下面是最小的工作代码。
import sys
from PyQt5.QtCore import *
from PyQt5.QtSvg import *
from PyQt5.QtWidgets import *
svg_image = 'C:\\dev\\io\SVG\\my_image.svg'
class Image(QGraphicsSvgItem):
def __init__(self, parent=None):
super().__init__(svg_image)
self.parent = parent
self.setFlags(QGraphicsItem.ItemIsSelectable |
QGraphicsItem.ItemIsMovable)
self.setAcceptHoverEvents(True)
self.mobile = True # allows the svg to be dragged around
self.svgSize = self.renderer().defaultSize()
self.width = self.svgSize.width()
self.height = self.svgSize.height()
def hoverEnterEvent(self, event):
print('Enter')
def hoverLeaveEvent(self, event):
print('Leave')
def hoverMoveEvent(self, event):
if self.mobile: #
# this is a bit flaky in that the object detaches from mouse if mouse movement is too abrubt..
self.setPos(event.scenePos() - QPoint(self.width / 2, self.height / 2))
self.update()
def mousePressEvent(self, event):
self.mobile = False # stop the hover/move behaviour
super().mousePressEvent(event)
class Viewport(QGraphicsView):
def __init__(self, parent=None):
super(Viewport, self).__init__(parent)
self.scene = QGraphicsScene()
self.image = Image()
self.image.setPos(100, 100)
self.scene.addItem(self.image)
self.setScene(self.scene)
self.image.scene = self.scene
self.image.view = self
class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.view = Viewport(self)
hbox = QHBoxLayout()
hbox.addWidget(self.view)
self.setLayout(hbox)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
这工作,直到用户突然移动鼠标,光标与图像失去接触,导致hoverMoveEvent不再被调用,图像位置不再更新。我希望这个图像拖动功能更加 "粘性",当变量 "self.mobile"==True时,hoverMoveEvent就没有机会不被触发,而图像的位置会一直更新,直到self.mobile变成False。
这至少是我的想法。我想知道如何实现这样的东西?
让鼠标更有粘性的一种方法是将移动物品的责任转移到图形视图中,而不是物品本身。例如,像这样的做法可以使场景中的一个项目通过点击它们一次而成为移动的,通过点击它们第二次而成为非移动的。
class Viewport(QGraphicsView):
def __init__(self, parent=None):
...
self.move_item = None
self.pos0 = None
def mousePressEvent(self, event):
item = self.itemAt(event.pos())
if self.move_item:
self.move_item = None
self.pos0 = None
else:
self.move_item = item
self.pos0 = self.move_item.pos() - self.mapToScene(event.pos())
def mouseMoveEvent(self, event):
if self.move_item and self.pos0:
self.move_item.setPos(self.mapToScene(event.pos()) + self.pos0)