0

QGraphicsPixmapItem 和 QGraphicsItem 一样,有一个方法 update(x0, y0, width, height),以便仅在 QGraphicsScene 上重绘一个像素图。调用它会在 QGraphicsItem 上安排一个 paint()(在 Qt 的事件循环中),并且在执行这个 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
    }
};

另一种选择是保留 QGraphicsPixmapItem 的“内部 QPixmap”,并将 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);”的替代品,它不会重绘整个东西,但效果很好。任何输入都非常感谢:)

4

1 回答 1

1

在我提出解决方案之前,有几点想法:

首先,Graphics View 框架旨在成为显示许多图形对象的解决方案,因此一张大图像并不那么合适。当然,我意识到你的例子可能只是一个人为的例子,所以这一点可能并不适用。其次,由于该框架非常以变换为中心,因此仅重绘 QGraphicsItem 的一部分可能没有意义,除非所有变换都是相同的,没有滚动等。

无论如何,如果您只想绘制 QGraphicsItem 的一部分,您可以简单地存储需要更新的矩形,并从您的paint()方法内部访问它。例如:

CustomItem::setPaintRect(const QRectF &rect)
{
    paintRect = rect;
    update();
}

CustomItem::paint(QPainter *painter /* etc. */)
{
    painter->fillRect(paintRect, brush);
}
于 2012-05-23T16:49:58.620 回答