PySide:让 SVG 图像跟随鼠标而无需拖放?

Posted

技术标签:

【中文标题】PySide:让 SVG 图像跟随鼠标而无需拖放?【英文标题】:PySide: Have an SVG image follow mouse without drag and drop? 【发布时间】:2016-08-03 17:13:43 【问题描述】:

我正在尝试将 SVG 图像放置在最终将成为另一个应用程序中的 QGroupBox 中。然后,在第一次单击 SVG 时,SVG “粘”在鼠标上(就像在拖放过程中按住鼠标按钮一样)。第二次单击将释放(“放下”)图像。

我一直在阅读但不太了解小部件、项目、场景和视图之间的本质/关系。我下面的代码有点工作,但不太正确。图像几乎主动避开鼠标。对于非 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_())

【问题讨论】:

【参考方案1】:

PySide 邮件列表上的 Jukka 能够通过以下回复帮助我:

你不必在QGraphicsView做任何事情,你可以拥有 mousePressEventImage 中切换浮动开和关。这些 事件获取 QGraphicsMouseEvents 作为参数,这些具有 您需要的有关光标位置或鼠标按下位置的信息。所以,在 简而言之,从Viewport 中删除mousePressEvent 并替换 hoverMoveEvent 在您的 Image 中使用它,它将起作用:

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 图像跟随鼠标而无需拖放?的主要内容,如果未能解决你的问题,请参考以下文章

C# 具有叠加/不透明图像的拖放效果

我在使用 Unity 在 VR 中拖放对象时遇到问题

用d3.behavior.drag拖拽的时候为啥svg图是默认的左上角跟随鼠标的移动吗

如何通过 Pygame 2.5 让 2 个单独的图像相互追逐并相互跟随?

HTML5新属性-----拖放

PySide 填空 TableModel