从PyQt5中的QGraphicsScene中选择项目

问题描述 投票:0回答:1

我正在使用QGraphicsView和QGraphicsSCene加载图像。我在QGraphicsScene中有多个RectItems。代码在下面;

def load_image(self,image_item):
    rect_list = [[20,30,70,35],[50,100,60,100],[410,450,60,100]]
    self.pic = QPixmap(str(image_item.text()))
    self.scene = QGraphicsScene(self.centralWidget)
    self.brush = QBrush(Qt.BDiagPattern)
    self.pen = QPen(Qt.red)
    self.pen.setWidth(2)
    self.load_view = self.scene.addItem(QGraphicsPixmapItem(self.pic))
    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) #Item is Selectable
        self.rect_item.setFlag(QGraphicsItem.ItemIsMovable) # Item is Movable

    self.gView.setScene(self.scene)
    self.gView.setRenderHint(QPainter.Antialiasing)
    self.gView.show()

现在,当我从QgraphicsScene中的项目列表中单击一个rect_item时,我想打印该项目。

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS8zaHZZOS5wbmcifQ==” alt =“此处提供了屏幕截图”>

python pyqt qgraphicsview qgraphicsscene
1个回答
0
投票

我认为,最简单的解决方案是,如果只需要“单击项目”消息,则将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需要某种信号/插槽机制,则还可以将场景子类化,并使该项目发出其信号。这不是best做法,但它有效:-)

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))
© www.soinside.com 2019 - 2024. All rights reserved.