【问题标题】:How do I limit the mouse to a QGraphicsScene in PySide?如何将鼠标限制在 PySide 中的 QGraphicsScene 上?
【发布时间】:2017-02-23 23:33:45
【问题描述】:

或者可能是 QGraphicsView?我仍然不了解映射。看评论

# I'm not computing x and y correctly. mapTo/From/Global/Scene/???

myview.py 下面。这个想法是,当您单击环时,它会切换移动性,将其绑定到鼠标移动,直到您再次单击 - 即第一次单击将其设置为“拖动”,第二次将其设置为“放下”。

这很好,但是当我离开“框架”(视图/场景)然后重新进入其他地方时,戒指会跳到新位置。我想防止戒指在“移动”或“中”时离开拖动”模式。

主要代码

# Form implementation generated from reading ui file 'frames.ui'
# ...and then adjusted by hand... a lot

from PySide.QtCore import *
from PySide.QtGui  import *
from myview        import *


class Frames(QDialog):
    def __init__(self, parent=None):
        super(Frames, self).__init__(parent)

        self.verticalLayout = QVBoxLayout()

        self.setWindowFlags(Qt.FramelessWindowHint)

        self.topBox = QGroupBox()
        sizePolicy = QSizePolicy(QSizePolicy.Preferred,
                                 QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.topBox
                                     .sizePolicy().hasHeightForWidth())
        self.topBox.setSizePolicy(sizePolicy)
        self.verticalLayout.addWidget(self.topBox)

        self.middleBox = QGroupBox()
        sizePolicy = QSizePolicy(QSizePolicy.Preferred,
                                 QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(10)
        sizePolicy.setHeightForWidth(self.middleBox
                                     .sizePolicy().hasHeightForWidth())
        self.middleBox.setSizePolicy(sizePolicy)
        self.horizontalLayout = QHBoxLayout(self.middleBox)

        self.view = MyView(self)
        self.horizontalLayout.addWidget(self.view)

        self.rightBox = QGroupBox(self.middleBox)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred,
                                 QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.rightBox
                                     .sizePolicy().hasHeightForWidth())
        self.rightBox.setSizePolicy(sizePolicy)
        self.horizontalLayout.addWidget(self.rightBox)
        self.verticalLayout.addWidget(self.middleBox)

        self.bottomBox = QGroupBox()
        sizePolicy = QSizePolicy(QSizePolicy.Preferred,
                                 QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.bottomBox
                                     .sizePolicy().hasHeightForWidth())
        self.bottomBox.setSizePolicy(sizePolicy)
        self.verticalLayout.addWidget(self.bottomBox)
        self.setLayout(self.verticalLayout)
        self.showFullScreen()

        QMetaObject.connectSlotsByName(self)


def main():
    import sys
    app = QApplication(sys.argv)
    frames = Frames()
    frames.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

还有 myview.py

from PySide.QtCore import *
from PySide.QtGui  import *


class Ring(QGraphicsEllipseItem):

    def __init__(self, parent=None):
        super(Ring, self).__init__(0, 0, 80, 80, parent)
        self.mobile   = 0     # Initially immobile

        self.setFlags(QGraphicsItem.ItemIsMovable)
        self.setAcceptsHoverEvents(True)

    def mousePressEvent(self, event):
        super(Ring, self).mousePressEvent(event)
        self.mobile = (self.mobile + 1) % 2  # Toggle mobility


class MyView(QGraphicsView):

    def __init__(self, parent=None):
        super(MyView, self).__init__(parent)
        self.installEventFilter(self)

        sizePolicy = QSizePolicy(QSizePolicy.Expanding,
                                 QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(2)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)

        self.scene = QGraphicsScene(self)
        self.ring  = Ring()
        self.scene.addItem(self.ring)
        self.curse = self.cursor()

    def eventFilter(self, obj, event):
        super(MyView, self).eventFilter(obj, event)
        if event.type() == QEvent.WindowActivate:

            self.setWindowFlags(Qt.FramelessWindowHint)
            self.setFrameShape(QFrame.NoFrame)

            bounds = self.geometry()

            self.X1, self.Y1, self.w,  self.h  = bounds.getRect()
            self.X1, self.Y1, self.X2, self.Y2 = bounds.getCoords()

            self.scene.setSceneRect(self.X1, self.Y1,
                                    self.w, self.h)

            self.cx  = bounds.center().x()
            self.cy  = bounds.center().y()

            self.ring.setPos(self.cx - 40, self.cy - 40)

            self.setScene(self.scene)
            brush = QBrush(QColor(255, 255, 127))
            brush.setStyle(Qt.SolidPattern)
            self.setBackgroundBrush(brush)

            self.removeEventFilter(obj)
        return False

    def mouseMoveEvent(self, event):
        super(MyView, self).mouseMoveEvent(event)
        if self.ring.mobile:

# I'm not computing x and y correctly. mapTo/From/Global/Scene/???

            x = min(max(event.pos().x(), self.X1), self.X2)
            y = min(max(event.pos().y(), self.Y1), self.Y2)
#           self.curse.setPos(x, y)

            self.ring.setPos(event.pos())

【问题讨论】:

    标签: python pyside qgraphicsview coordinate-systems qgraphicsscene


    【解决方案1】:

    真正的鼠标光标是由窗口环境管理的,而不是 Qt,所以我认为在那个级别上没有办法做到这一点。至少不是以跨平台的方式。但是你可以伪造它。

    • 隐藏真正的光标,可以设置为Qt::BlankCursor
    • 跟踪实际光标相对于您要限制的区域的位置。
    • 在 Qt 中将您自己的虚拟光标绘制为图形对象。
    • 自行管理虚拟光标的位置。

    但是,这不会阻止真正的光标“点击”出您的应用程序并与其他应用程序交互。您可能必须检测到这种情况的发生,然后光标单击回您的应用程序并让它恢复对虚拟光标的控制。这样,当真正的光标“回来”时,您可以恢复虚拟光标从之前的最后一个位置移动,而不是真正光标的当前位置。

    【讨论】:

    • 哎呀!好吧,如果这是真的,至少我对没有找到解决方法感到不那么愚蠢。 “永远看在……光明的一面”
    • 我不担心用户与其他应用程序交互。我的应用程序会全屏显示,用户将被指示不要使用 Alt-、Command- 或其他任何东西。如果他们无视这些指示,那不是我的问题。
    猜你喜欢
    • 2016-03-26
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2015-10-20
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多