PySide:让 SVG 图像跟随鼠标移动而无需拖放?
PySide: Have an SVG image follow mouse without drag and drop?
我正在尝试将 SVG 图像放置在另一个应用程序中最终将成为 QGroupBox 的位置。然后,在第一次单击 SVG 时,SVG "sticks" 到鼠标(就像在拖放过程中按住鼠标按钮一样)。第二次单击将释放 ("drop") 图像。
我一直在阅读但不太了解小部件、项目、场景和视图之间的性质/关系。我下面的代码可以工作,但不太正确。图像几乎主动避开了鼠标。对于非 C、非 C++、PyQt/PySide 初学者,在某处有明确的解释吗?或者对我哪里出错有简单的解释吗?
#!/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_())
PySide 邮件列表中的 Jukka 能够通过以下回复帮助我:
You don’t have to do anything in QGraphicsView
, you can have
mousePressEvent
in Image
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, remove mousePressEvent
from Viewport
and replace
hoverMoveEvent
in your Image
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)
我正在尝试将 SVG 图像放置在另一个应用程序中最终将成为 QGroupBox 的位置。然后,在第一次单击 SVG 时,SVG "sticks" 到鼠标(就像在拖放过程中按住鼠标按钮一样)。第二次单击将释放 ("drop") 图像。
我一直在阅读但不太了解小部件、项目、场景和视图之间的性质/关系。我下面的代码可以工作,但不太正确。图像几乎主动避开了鼠标。对于非 C、非 C++、PyQt/PySide 初学者,在某处有明确的解释吗?或者对我哪里出错有简单的解释吗?
#!/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_())
PySide 邮件列表中的 Jukka 能够通过以下回复帮助我:
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)