python - PyQt5:关于 QGraphicsScene 的 itemAt() 和 focusItemChanged() 的问题

标签 python pyqt pyqt5

我有两个问题:

  1. QTransform() 在 itemAt() 中意味着什么?下面这句话是Qt doc中的内容,但我看不懂:

deviceTransform is the transformation that applies to the view, and needs to be provided if the scene contains items that ignore transformations.

  • 为什么 focusItemChanged 信号不起作用?
  • 这是我的代码:

    import sys
    from PyQt5.QtGui import QTransform
    from PyQt5.QtWidgets import QApplication, QGraphicsItem, QGraphicsScene, QGraphicsView
    
    
    class Demo(QGraphicsView):
        def __init__(self):
            super(Demo, self).__init__()
            self.resize(300, 300)
    
            self.scene = QGraphicsScene()
            self.scene.setSceneRect(0, 0, 300, 300)
    
            self.rect = self.scene.addRect(100, 30, 100, 30)
            self.ellipse = self.scene.addEllipse(100, 80, 50, 40)
    
            self.rect.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
            self.ellipse.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
    
            self.setScene(self.scene)
    
            # Question 1
            print(self.scene.itemAt(110, 40, QTransform()))
    
            # Question 2
            self.scene.focusItemChanged.connect(self.my_slot)
    
        def my_slot(self, new_item, old_item):
            print(new_item)
            print(old_item)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        demo = Demo()
        demo.show()
        sys.exit(app.exec_())
    

    如有任何帮助,我们将不胜感激。

    最佳答案

    <强>1。 itemAt() 中的 QTransform() 是什么意思?

    正如它在文档中指出的那样,如果有一个项目忽略转换,则只需要传递 deviceTransform ,那么如何做到让项目不支持转换呢?您必须启用标志Qt::ItemIgnoresTransformations

    使用您的代码,您看不到差异,因此我实现了以下示例,其中有 2 个项目,其中一个项目激活了 ItemIgnoresTransformations 标志,另一个则没有。然后,当您按下任何项目时,预计该项目将在控制台中打印,但是如果您传递 QTransform (),如果您按下单选按钮传递 viewportTransform,您将看到具有 ItemIgnoresTransformations 标志的项目返回 None () 你会看到现在这两项都打印在控制台上。因此,如果有任何项目启用了 ItemIgnoresTransformations 标志,则必须传递 deviceTransform。

    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Demo(QtWidgets.QGraphicsView):
        def __init__(self):
            super(Demo, self).__init__()
            self._scene = QtWidgets.QGraphicsScene()
            self._scene.setSceneRect(0, 0, 300, 300)
            self.setScene(self._scene)
            self.rect1 = self._scene.addRect(
                100, 30, 100, 30, brush=QtGui.QBrush(QtGui.QColor("red"))
            )
            self.rect1.setFlag(QtWidgets.QGraphicsItem.ItemIgnoresTransformations)
    
            self.rect2 = self._scene.addRect(
                200, 30, 100, 30, brush=QtGui.QBrush(QtGui.QColor("green"))
            )
    
            self.rotate(50)
            self._use_deviceTransform = False
    
        def mousePressEvent(self, event):
            sp = self.mapToScene(event.pos())
            item = self._scene.itemAt(
                sp,
                self.viewportTransform()
                if self._use_deviceTransform
                else QtGui.QTransform(),
            )
            print(item)
    
        def set_use_deviceTransform(self, t):
            self._use_deviceTransform = t
    
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        radiobutton = QtWidgets.QRadioButton("use deviceTransform")
        demo = Demo()
        radiobutton.toggled.connect(demo.set_use_deviceTransform)
        w = QtWidgets.QWidget()
        lay = QtWidgets.QVBoxLayout(w)
        lay.addWidget(radiobutton)
        lay.addWidget(demo)
        w.show()
        w.resize(640, 480)
        sys.exit(app.exec_())
    

    <强>2。为什么 focusItemChanged 信号不起作用?

    如果项目的焦点发生变化,则会触发信号,但默认情况下项目没有焦点,因此不会发出信号,解决方案是激活标志 QGraphicsItem::ItemIsFocusable:

    import sys
    from PyQt5.QtGui import QTransform
    from PyQt5.QtWidgets import QApplication, QGraphicsItem, QGraphicsScene, QGraphicsView
    from PyQt5.QtCore import pyqtSlot, Qt
    
    
    class Demo(QGraphicsView):
        def __init__(self):
            super(Demo, self).__init__()
            self.resize(300, 300)
    
            self.scene = QGraphicsScene()
            self.scene.setSceneRect(0, 0, 300, 300)
    
            self.rect = self.scene.addRect(100, 30, 100, 30)
            self.ellipse = self.scene.addEllipse(100, 80, 50, 40)
    
            self.rect.setFlags(
                QGraphicsItem.ItemIsMovable
                | QGraphicsItem.ItemIsSelectable
                | QGraphicsItem.ItemIsFocusable
            )
            self.ellipse.setFlags(
                QGraphicsItem.ItemIsMovable
                | QGraphicsItem.ItemIsSelectable
                | QGraphicsItem.ItemIsFocusable
            )
    
            self.setScene(self.scene)
            self.scene.focusItemChanged.connect(self.my_slot)
    
        @pyqtSlot("QGraphicsItem*", "QGraphicsItem*", Qt.FocusReason)
        def my_slot(self, new_item, old_item, reason):
            print(old_item, new_item)
    

    关于python - PyQt5:关于 QGraphicsScene 的 itemAt() 和 focusItemChanged() 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55824951/

    相关文章:

    python - 使用 PyQt 的组合框中的复选框

    python - pip3 安装命令重复失败,无法创建文件 '/tmp/pip-install-xxxxx/package'

    python - 如何在 Tkinter 的窗口或框架内设置所有小部件的填充

    python - 将 .py 转换为 .ui 文件

    python - “NoneType”对象在python小程序中没有属性 'get'

    python - PyQt 将graphicsScene 对象分组为一个对象

    python - 在 KDE Linux 上部署 QtQuick QML Python 项目

    python - Pyqt5 在小部件上居中小部件

    python - 用 Python 解析一个非常大的文本文件?

    python - 测试一个值是否在一个集合中并分配变量