问题
I have two questions:
- what does QTransform() mean in itemAt()? The sentence below is what it says in Qt doc, but I can't understand:
deviceTransform is the transformation that applies to the view, and needs to be provided if the scene contains items that ignore transformations.
- 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:
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)
来源:https://stackoverflow.com/questions/55824951/pyqt5-questions-about-qgraphicsscenes-itemat-and-focusitemchanged