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);
}
Другие вопросы по тегам