QGraphicsPixmapItem
QGraphicsPixmapItem, как и QGraphicsItem, имеет обновление метода (x0, y0, width, height), чтобы перерисовывать растровое изображение только частично в QGraphicsScene. Вызов этого приведет к планированию paint() (в цикле событий Qt) на QGraphicsItem, и после выполнения этого paint () ограничивающая рамка (x,y,width,height) будет перерисована в QGraphcisScene.
К сожалению, нет способа запланировать событие рисования с помощью ограничивающего прямоугольника, что означает, что QGraphicsPixmapItem::paint() вынужден перерисовывать весь QPixmap, поэтому переопределение этого метода paint () в подклассе не дает обновлять QPixmap только частично, поэтому небольшое (локальное) обновление QPixmap недопустимо медленно.
Такой подкласс будет выглядеть примерно так:
class LocallyUdatablePixmapItem : public QGraphicsPixmapItem {
private:
QImage ℑ
public:
LocallyUdatablePixmapItem(QImage &img) : QGraphicsPixmapItem(), image(img) {}
paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QStyle *widget) {
//locall update, unfortunately without a boundig box :( therefore -> slow
}
};
Другой вариант - сохранить "внутреннюю QPixmap" QGraphicsPixmapItem и частично нарисовать QImage, например, так:
//some initialization of variables
QGraphicsScene scene = ...;
QImage img = ...; //some image data that I wish to manipulate from time to time
QPixmap pixmap = QPixmap::fromImage(this->shown);
QPainter painter = new QPainter(&this->pixmap);
QGraphicsPixmapItem item = this->addPixmap(this->pixmap);
item->setPixmap(this->pixmap);
//this should not matter, but actually it does, as I will explain shortly
//delete painter;
//painter = new QPainter(item->pixmap());
//For some reason I decide to update (manimulate) img within a small boundigbox
int x0, y0, width, height; //bounding box, assume they are set to whatever is appropriate for the previous update
painter->drawImage (x0, y0, img, x0, y0, width, height);
//now the pixmap is updated, unfortunately the item is not. This does not affect it:
item->update(x0, y0, width, height);
//nor does this:
item->update();
//but this, which makes the whole thing slow, does:
item.setPixmap(&pixmap);
Учитывая, что мне нужно установить растровое изображение для его исправления, я предположил, что он как-то не был установлен при инициализации, поэтому раскомментирование упомянутых строк раньше казалось хорошей идеей. К сожалению, вызов drawImage() затем переходит в:
QPaintDevice: Невозможно уничтожить нарисованное устройство рисования
Я хотел бы иметь альтернативу "item.setPixmap(&pixmap);", которая не перерисовывает все, но работает хорошо. Любой вклад очень хорошо ценится:)
1 ответ
Прежде чем я предлагаю решение, несколько мыслей:
Во-первых, каркас графического представления предназначен для решения многих графических объектов, поэтому одно большое изображение не совсем подходит. Конечно, я понимаю, что ваш пример, вероятно, просто надуманный, так что этот пункт может и не применяться. Во-вторых, поскольку среда очень ориентирована на преобразование, может не иметь смысла перерисовывать только части QGraphicsItem, если все преобразования не являются идентичными, прокрутка не выполняется и т. Д.
В любом случае, если вы хотите нарисовать только часть QGraphicsItem, вы можете просто сохранить прямоугольник, который необходимо обновить, и получить к нему доступ изнутри вашего paint()
метод. Например:
CustomItem::setPaintRect(const QRectF &rect)
{
paintRect = rect;
update();
}
CustomItem::paint(QPainter *painter /* etc. */)
{
painter->fillRect(paintRect, brush);
}