Issue
I'm following the idea in this post:
https://stackoverflow.com/a/38860809/2407089
where the hoverMoveEvent method in the QGraphicsSvgItem class allows someone to drag an image around a scene, via self.scenePos and self.setPos. Minimal working code below:
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_())
This works, until the user abruptly moves the mouse and the cursor loses contact with the image- resulting in the hoverMoveEvent no longer being called, and the image position no longer updating. I would like this image drag functionality to be more 'sticky', in that when the variable 'self.mobile' == True, there's no chance of the hoverMoveEvent not triggering, and the image position is always updated until self.mobile is False.
That's atleast the idea. Wondering how I could implement something like that?
Solution
One way to make the mouse more sticky is to move the responsibility of moving the items to the graphics view instead of the items themselves. For example, something like this would make an item in the scene mobile by clicking on them once and non-mobile by clicking on them for a second time:
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)
Answered By - Heike
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.