Issue
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_())
Solution
Jukka on the PySide mailing list was able to help me out with the following response:
You don’t have to do anything in
QGraphicsView
, you can havemousePressEvent
inImage
to toggle floating on and off. These events get QGraphicsMouseEvents as parameters and these have the information you need about position of cursor or mouse press. So, in short, removemousePressEvent
fromViewport
and replacehoverMoveEvent
in yourImage
with this and it will work:
def hoverMoveEvent(self, event):
if self.mobile:
print("Moving")
self.setPos(event.scenePos() - QPoint(self.width / 2, self.height / 2))
def mousePressEvent(self, event):
self.mobile = not self.mobile # Toggle mobility
super().mousePressEvent(event)
Answered By - Ubuntourist
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.