Рисование границы QGraphicsPixmapItem при наведении

Я пытаюсь создать свой собственный QGraphicsPixmapItem, где я могу активироваться в режиме наведения, и я хочу рисовать черную рамку, когда я нахожусь над прямоугольником элемента, и возвращаюсь к нормальному состоянию, когда я покидаю прямоугольное пространство.

Я запустил этот код, но не знаю, что делать дальше. Также хотел сделать paintEvent, но у QGraphicsPixmapItems этого нет. Так что я еще больше запутался, так как не думаю, что метод рисования будет таким же.

class PixmapItem(QGraphicsPixmapItem):
    def __init__(self, pixmap, rect, parent=None):
        super().__init__(parent)
        self.pixmap = pixmap
        self.setPixmap(self.pixmap)
        self.rect = rect
        self.setAcceptHoverEvents(True)

    def hoverEnterEvent(self, *args, **kwargs):
        pass

Я мог бы заставить наведение печатать «привет», но не могу сделать ничего другого, даже с некоторыми примерами, потому что они связаны с paintEvent и другими типами элементов.

Я хотел бы сохранить тип элемента, если это возможно, и нарисовать границу, как я сказал. Но также не знаю, будет ли это лучшим подходом, который также прост.


person Black Mage    schedule 22.05.2019    source источник


Ответы (1)


QGraphicsItem не имеет метода paintEvent, но имеет метод paint() :

from PyQt5 import QtCore, QtGui, QtWidgets


class PixmapItem(QtWidgets.QGraphicsPixmapItem):
    def __init__(self, pixmap, parent=None):
        super().__init__(pixmap, parent)
        self.setAcceptHoverEvents(True)
        self._is_hovered = False

    def hoverEnterEvent(self, event):
        self._is_hovered = True
        self.update()
        super().hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        self._is_hovered = False
        self.update()
        super().hoverLeaveEvent(event)

    def paint(self, painter, option, widget=None):
        super().paint(painter, option, widget)
        if self._is_hovered:
            painter.save()
            pen = QtGui.QPen(QtGui.QColor("black"))
            pen.setWidth(4)
            painter.setPen(pen)
            painter.drawRect(self.boundingRect())
            painter.restore()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    scene = QtWidgets.QGraphicsScene()
    view = QtWidgets.QGraphicsView(scene)
    item = PixmapItem(QtGui.QPixmap("image.png"))
    scene.addItem(item)
    view.resize(640, 480)
    view.show()
    sys.exit(app.exec_())

Обновление:

def paint(self, painter, option, widget=None):
    super().paint(painter, option, widget)
    if self._is_hovered:
        painter.save()
        pen = QtGui.QPen(QtGui.QColor("black"))
        pen.setWidth(4)
        painter.setPen(pen)
        r = self.boundingRect()
        r.adjust(0, 0, -pen.width()/2, -pen.width()/2)
        painter.drawRect(r)
        painter.restore()
person eyllanesc    schedule 22.05.2019
comment
как метод рисования узнает, где находится ограничивающий прямоугольник, если QRect не определен? Не имеет смысла для меня. Я программировал с PyQt только на этой неделе, так что все это действительно ново для меня. - person Black Mage; 23.05.2019
comment
@BlackMage Во всех QGraphicsItem определено boundingRect, в случае QGraphicsPixmapItem — это прямоугольник, занимающий растровое изображение. Я рекомендую вам прочитать doc.qt.io/qt-5/graphicsview.html - person eyllanesc; 23.05.2019
comment
Хорошо, спасибо! Но еще один момент, ширина в моем изображении отличается по правой и нижней границам, они более тонкие. Это было бы из-за моего базового кода/пиксельной карты? - person Black Mage; 23.05.2019
comment
@BlackMage Насколько велико ваше изображение? - person eyllanesc; 23.05.2019
comment
это изображение PNG размером 16x16, масштабированное в моей программе до 32x32. - person Black Mage; 23.05.2019
comment
Попробуйте с моим обновлением, что происходит, так это то, что QPen берет внутренний край в верхнем левом углу и внешний край в правом нижнем углу. - person eyllanesc; 23.05.2019
comment
Извините за расширение этого комментария, но как мне нарисовать произвольный QRect в том же коде? Я попытался нарисовать ограничивающий прямоугольник кодом, а также другой прямоугольник и не смог. Даже замена r на любой QRect ничего не нарисует. Так что это просто работает для ограничивающего прямоугольника для меня. - person Black Mage; 23.05.2019
comment
@BlackMage QRectf, который можно было бы нарисовать, должен иметь пересечение с boundingRect, потому что, если его нет, он не будет окрашен, boundingRect подобен холсту художника. Я рекомендую прочитать ссылку, которую я предоставил в одном из своих комментариев, поскольку QGraphicsView и QGraphicsView обрабатывают многие системы координат. Прочтите документацию и просмотрите примеры Qt или примеры, которые изобилуют в Интернете, потому что в противном случае вы слишком усложните, это не изучается за один день. - person eyllanesc; 23.05.2019