Я думаю, что самое простое решение, если вам действительно нужно только сообщение "элемент нажал", это добавить флаг Qt.ItemIsFocusable к элементу и затем использовать сигнал focusItemChanged сцены:
def load_image(self, image_item):
# ...
self.scene = QGraphicsScene(self.centralWidget)
self.scene.focusItemChanged.connect(self.focusChanged)
# ...
for rect in rect_list:
self.rect_item = self.scene.addRect(rect[0],rect[1],rect[2],rect[3],self.pen,self.brush) # x,y,w,h
self.rect_item.setFlag(QGraphicsItem.ItemIsSelectable)
self.rect_item.setFlag(QGraphicsItem.ItemIsMovable)
# required for focusItemChanged signal to work:
self.rect_item.setFlag(QGraphicsItem.ItemIsFocusable)
def focusItemChanged(self, newItem, oldItem, reason):
if newItem and reason == Qt.MouseFocusReason:
print('item {} clicked!'.format(newItem))
У этого метода есть некоторые проблемы, но, самое главное, тот факт, что если элемент уже выбран (следовательно, у него есть фокус), вы не получите сигнал.
Нет немедленного решения для этого, потому чтобазовые элементы QGraphicsItems не являются потомками QObject, что означает, что они не могут излучать какой-либо сигнал.
Если вам не требуется поддержка сигнала / слота, вы можете создать подкласс QGraphicsRectItem и переопределить его mousePressEvent:
class ClickableGraphicsRectItem(QGraphicsRectItem):
def __init__(self, x, y, w, h, pen, brush):
super(ClickableGraphicsRectItem, self).__init__(x, y, w, h)
self.setPen(pen)
self.setBrush(brush)
# flags can be set all at once using the "|" binary operator
self.setFlags(self.ItemIsSelectable|self.ItemIsMovable)
def mousePressEvent(self, event):
super(ClickableGraphicsRectItem, self).mousePressEvent(event)
if event.button() == Qt.LeftButton:
print('item clicked!')
class MyProgram(QMainWindow):
def load_image(self, image_item):
# ...
for rect in rect_list:
self.rect_item = ClickableGraphicsRectItem(...)
Если вам do нужен какой-то механизм сигнала / слота, вы также можете создать подкласс сцены и заставить элемент излучать свой сигнал. Это не лучшая практика, но она работает: -)
class ClickableGraphicsRectItem(QGraphicsRectItem):
# ...
def mousePressEvent(self, event):
super(ClickableGraphicsRectItem, self).mousePressEvent(event)
if event.button() == Qt.LeftButton:
self.scene().itemClicked(self)
class ItemClickableGraphicsScene(QGraphicsScene):
itemClicked = pyqtSignal(QGraphicsItem)
class MyProgram(QMainWindow):
def load_image(self, image_item):
# ...
self.scene = ItemClickableGraphicsScene(self.centralWidget)
self.scene.itemClicked.connect(self.itemClicked)
# ...
for rect in rect_list:
self.rect_item = ClickableGraphicsRectItem(...)
def itemClicked(self, item):
print('item {} clicked!'.format(item))
В качестве альтернативы, вы можете переопределить mousePressEvent графического представления. В этом примере я просто проверяю, является ли это QGraphicsRectItem (поскольку у вас также есть QGraphicsPixmapItem), но если вы добавляете другие типы элементов, вам нужно будет найти способ «распознать» их более тщательно.
class ClickableItemView(QGraphicsView):
def mousePressEvent(self, event):
super(ClickableItemView, self).mousePressEvent(event)
if event.button() == Qt.LeftButton:
item = self.itemAt(event.pos())
if isinstance(item, QGraphicsRectItem):
print('item {} clicked!'.format(item))