QGraphicsObject нуждается в явном обновлении для перерисовки - PullRequest
1 голос
/ 18 марта 2020

У меня есть QGraphicsPixmapItem, содержимое которого меняется с помощью мыши. Все прекрасно работает, когда все интерактивные события обрабатываются внутри класса, полученного из QGraphicsPixmapItem:

import numpy as np
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QGraphicsPixmapItem, QGraphicsScene, QGraphicsView, QMainWindow

class MyQGraphicsPixmapItem(QGraphicsPixmapItem):

  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.setNewImage()

  def setNewImage(self):
    im = np.random.randint(255, size=(256, 256), dtype=np.uint8)
    pix = QPixmap.fromImage(QImage(im, im.shape[1], im.shape[0], QImage.Format_Grayscale8))
    self.setPixmap(pix)

  def mousePressEvent(self, event):
    self.setNewImage()

app = QApplication([])
window = QMainWindow()
window.setGeometry(100, 100, 400, 400)
view = QGraphicsView()
scene = QGraphicsScene()
gpix = MyQGraphicsPixmapItem()
scene.addItem(gpix)
view.setScene(scene)
window.setCentralWidget(view)
window.show()
app.exec()

Однако вместо того, чтобы обрабатывать события в классе, я хотел бы иметь возможность обрабатывать их в другом месте, как правило, в качестве обратных вызовов. В этом ответе представлены два варианта: использование QGraphicsObject или использование фильтров событий сцены, которые настоятельно рекомендуется, поскольку первый имеет большой вес. Однако, AFAIU, фильтры событий сцены создают события графического элемента, обработанные другим графическим элементом; Я хочу что-то более общее, где QWidget может обработать событие. Поэтому я думаю, что в моем случае мне нужно использовать QGraphicsObject.

. Я сделал простую модификацию вышеприведенного сценария, чтобы обернуть QGraphicsPixmapItem в QGraphicsObject. Однако, что удивило меня, так это то, что изображение не обновляется sh при нажатии.

import numpy as np
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QGraphicsObject, QGraphicsPixmapItem, QGraphicsScene, QGraphicsView, QMainWindow

class MyQGraphicsObject(QGraphicsObject):

  def __init__(self, gpix):
    super().__init__(gpix)
    self.gpix = gpix
    self.setNewImage()

  def setNewImage(self):
    im = np.random.randint(255, size=(256, 256), dtype=np.uint8)
    pix = QPixmap.fromImage(QImage(im, im.shape[1], im.shape[0], QImage.Format_Grayscale8))
    self.gpix.setPixmap(pix)
    # self.update()  # needs to be uncommented to refresh

  def mousePressEvent(self, event):
    self.setNewImage()

  def boundingRect(self):
    return self.gpix.boundingRect()

  def paint(self, painter, option, widget):
    return self.gpix.paint(painter, option, widget)

app = QApplication([])
window = QMainWindow()
window.setGeometry(100, 100, 400, 400)
view = QGraphicsView()
scene = QGraphicsScene()
opix = MyQGraphicsObject(QGraphicsPixmapItem())
scene.addItem(opix)
view.setScene(scene)
window.setCentralWidget(view)
window.show()
app.exec()

Только если я вручную добавлю self.update(), изображение будет обновляться sh. Конечно, это решает проблему, но у меня есть ощущение, что это не нужно, и я неправильно использую QGraphicsObject. Это тот случай, или руководство update действительно нужно?

1 Ответ

2 голосов
/ 18 марта 2020

Правильно вызывать метод update().


TL; DR;

В каких случаях вам нужно вызывать update?

Всякий раз, когда разработчику необходимо вызвать метод paint () (или paintEvent для виджетов)

Почему в случае QGraphicsPixmapItem его не нужно вызывать, а в QGraphicsObject это необходимо?

В QGraphicsPixmap вызывается метод update(), и вы можете проверить, исходный код исправлен:

void QGraphicsPixmapItem::setPixmap(const QPixmap &pixmap)
{
    Q_D(QGraphicsPixmapItem);
    prepareGeometryChange();
    d->pixmap = pixmap;
    d->hasShape = false;
    <b>update();</b>
}

Другими словами, в QGraphicsItem вам больше не нужно вызывать его, потому что метод setPixmap уже делает это, в отличие от QGraphicsObject, который его не имеет, поэтому необходимо вызвать update () для принудительного вызова метода рисования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...