QGraphicsPixmapItem

时间:2012-05-23 14:21:26

标签: c++ qt qimage qpixmap

QGraphicsPixmapItem与QGraphicsItem一样,具有方法更新(x0,y0,width,height),以便仅部分地在QGraphicsScene上重绘像素图。调用它将在QGraphicsItem上调度paint()(在Qt的事件循环中),并且在执行此paint()之后,边界框(x,y,width,height)将被重绘为QGraphcisScene。

不幸的是,没有办法用一个boundingbox调度paint-event,这意味着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);

鉴于我需要设置pixmap来修复它,我认为它在某种程度上没有在初始化中设置,因此在之前取消注释所提到的行似乎是一个好主意。不幸的是,drawImage()调用然后将segfaults变成:

QPaintDevice:无法销毁正在绘制的绘图设备

我想替换“item.setPixmap(& pixmap);”,它不会重绘整个内容,但确实可以很好地工作。任何意见都非常赞赏:)

1 个答案:

答案 0 :(得分:1)

在我提出解决方案之前,先想一想:

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

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

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

CustomItem::paint(QPainter *painter /* etc. */)
{
    painter->fillRect(paintRect, brush);
}