本文介绍了PyQt5:关于 QGraphicsScene 的 itemAt() 和 focusItemChanged() 的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个问题:

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

deviceTransform 是应用于视图的转换,如果场景包含忽略转换的项目,则需要提供.

  1. 为什么 focusItemChanged 信号不起作用?

这是我的代码:

导入系统从 PyQt5.QtGui 导入 QTransform从 PyQt5.QtWidgets 导入 QApplication、QGraphicsItem、QGraphicsScene、QGraphicsView类演示(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)# 问题 1打印(self.scene.itemAt(110, 40, QTransform()))# 问题2self.scene.focusItemChanged.connect(self.my_slot)def my_slot(self, new_item, old_item):打印(新项目)打印(旧项目)如果 __name__ == '__main__':app = QApplication(sys.argv)演示 = 演示()演示.show()sys.exit(app.exec_())

任何帮助将不胜感激.

解决方案

1.QTransform() 在 itemAt() 中是什么意思?

因为它表明文档,如果有一个项目忽略转换,则只需要传递 deviceTransform,那么它是如何完成的,以便项目不支持转换?您必须启用标志 Qt::ItemIgnoresTransformations.

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

导入系统从 PyQt5 导入 QtCore、QtGui、QtWidgets类演示(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, 画笔=QtGui.QBrush(QtGui.QColor("red")))self.rect1.setFlag(QtWidgets.QGraphicsItem.ItemIgnoresTransformations)self.rect2 = self._scene.addRect(200, 30, 100, 30, 画笔=QtGui.QBrush(QtGui.QColor("green")))self.rotate(50)self._use_deviceTransform = Falsedef mousePressEvent(self, event):sp = self.mapToScene(event.pos())item = self._scene.itemAt(sp,self.viewportTransform()如果 self._use_deviceTransform否则 QtGui.QTransform(),)打印(项目)def set_use_deviceTransform(self, t):self._use_deviceTransform = t如果 __name__ == "__main__":app = QtWidgets.QApplication(sys.argv)radiobutton = QtWidgets.QRadioButton("use deviceTransform")演示 = 演示()radiobutton.toggled.connect(demo.set_use_deviceTransform)w = QtWidgets.QWidget()躺 = QtWidgets.QVBoxLayout(w)lay.addWidget(单选按钮)lay.addWidget(演示)w.show()w.resize(640, 480)sys.exit(app.exec_())

2.为什么 focusItemChanged 信号不起作用?

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

导入系统从 PyQt5.QtGui 导入 QTransform从 PyQt5.QtWidgets 导入 QApplication、QGraphicsItem、QGraphicsScene、QGraphicsView从 PyQt5.QtCore 导入 pyqtSlot, Qt类演示(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):打印(旧项目,新项目)

I have two questions:

  1. what does QTransform() mean in itemAt()? The sentence below is what it says in Qt doc, but I can't understand:
  1. why focusItemChanged signal is not working?

Here is my code:

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_())

Any help would be appreciated.

解决方案

1. what does QTransform() mean in itemAt()?

As it indicates the docs it is only necessary to pass the deviceTransform if there is an item that ignores the transformations, then how is it done so that an item does not support transformation? you must enable the flag Qt::ItemIgnoresTransformations.

With your code you can not see the difference so I have implemented the following example where there are 2 items one with the flag ItemIgnoresTransformations activated and the other not. Then when you press any of the items it is expected that the item will be printed in the console but you will see that the item that has the ItemIgnoresTransformations flag returns None if you pass QTransform (), if you press the radiobutton to pass the viewportTransform() you will see that Now both items are printed on the console. So you must pass the deviceTransform if there is any item with the flag ItemIgnoresTransformations enabled.

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. why focusItemChanged signal is not working?

The signal is triggered if the focus of an item changes, but by default the items have no focus so the signal is not emitted, the solution is to activate the flag 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)

这篇关于PyQt5:关于 QGraphicsScene 的 itemAt() 和 focusItemChanged() 的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 20:58