[PySide] SVG image follow mouse w/o drag and drop?

Kevin Cole dc.loco at gmail.com
Fri Aug 5 15:57:57 CEST 2016


Hi,

I'm trying to understand graphics items, scenes, views, widgets, and
not doing so well. I posted a question over on Stack Overflow, but
probably should have tried here first.

The question, copied below, is from
http://stackoverflow.com/questions/38749882/pyside-have-an-svg-image-follow-mouse-without-drag-and-drop

I'm trying to place an SVG image in what will eventually be a
QGroupBox in another application. Then, upon the first click over the
SVG, the SVG "sticks" to the mouse (as if the mouse button was held
down during a drag and drop). A second click will release ("drop") the
image.

I've been reading but not quite understanding the nature of /
relationship between Widgets, Items, Scenes and Views. My code below
sort of works but isn't quite right. The image almost actively avoids
the mouse. Is there a clear explanation somewhere for non-C, non-C++,
beginners with PyQt / PySide? Or is there a simple explanation for
where I've gone wrong?

#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import sys
from PySide.QtCore import *
from PySide.QtGui  import *
from PySide.QtSvg  import *


class Image(QGraphicsSvgItem):

    def __init__(self, parent=None):
        super(Image, self).__init__("image.svg", parent)
        self.parent = parent

        self.setFlags(QGraphicsItem.ItemIsSelectable |
                      QGraphicsItem.ItemIsMovable)

        self.setAcceptsHoverEvents(True)

        self.svgSize  = self.renderer().defaultSize()
        self.width    = self.svgSize.width()
        self.height   = self.svgSize.height()
        self.absolute = None  # Image's absolute (global) position
        self.mobile   = 0     # Initially immobile
        self.scene    = None  # Not in a scene yet
        self.view     = None  # Not in a view yet

    def hoverEnterEvent(self, event):
        print "Enter"

    def hoverLeaveEvent(self, event):
        print "Leave"

    def hoverMoveEvent(self, event):
        print "Moving"
        self.absolute = QCursor.pos()
        if self.view:
            relative = self.view.mapFromGlobal(self.absolute)
            if self.mobile:
#               self.setPos(relative)
                self.setPos(self.absolute)


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

    def mousePressEvent(self, event):
        super(Viewport, self).mousePressEvent(event)

        self.image.mobile = (self.image.mobile + 1) % 2  # Toggle mobility

        x = self.image.x()  # + int(self.image.width  / 2)
        y = self.image.y()  # + int(self.image.height / 2)
        QCursor.setPos(x, y)

        relative = self.mapFromGlobal(self.image.absolute)

        print "absolute.x() = {0}  absolute.y() = {1}"\
              .format(self.image.absolute.x(), self.image.absolute.y())

        print "relative.x() = {0}  relative.y() = {1}"\
              .format(relative.x(), relative.y())


class MainWindow(QWidget):

    def __init__(self, parent=None):
        super(MainWindow, self).__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_())



More information about the PySide mailing list