PySide:让 SVG 图像跟随鼠标而无需拖放? [英] PySide: Have an SVG image follow mouse without drag and drop?
问题描述
我正在尝试将 SVG 图像放置在另一个应用程序中最终将成为 QGroupBox 的位置.然后,在第一次单击 SVG 时,SVG粘"在鼠标上(就像在拖放过程中按住鼠标按钮一样).第二次点击将释放(放下")图像.
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.
我一直在阅读,但不太了解小部件、项目、场景和视图之间的性质/关系.我下面的代码可以正常工作,但不太正确.图像几乎主动避开鼠标.对于 PyQt/PySide 的非 C、非 C++ 初学者,是否有明确的解释?或者对我哪里出错有一个简单的解释?
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_())
推荐答案
PySide 邮件列表中的 Jukka 能够帮助我解决以下问题:
Jukka on the PySide mailing list was able to help me out with the following response:
你不必在QGraphicsView
中做任何事情,你可以有mousePressEvent
在 Image
中打开和关闭浮动.这些事件获取 QGraphicsMouseEvents 作为参数,这些具有您需要的有关光标或鼠标按下位置的信息.所以,在简而言之,从 Viewport
中删除 mousePressEvent
并替换hoverMoveEvent
在你的 Image
中,它会起作用:
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)
这篇关于PySide:让 SVG 图像跟随鼠标而无需拖放?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!