QGraphicsPixmapItem
QGraphicsPixmapItem与QGraphicsItem一样,具有方法update(x0,y0,width,height),以便仅在QGraphicsScene上部分重绘像素图。调用此函数将在QGraphicsItem上调度一次paint()(在Qt的事件循环中),并且在执行此paint()之后,边界框(x,y,宽度,高度)将重绘到QGraphcisScene。
不幸的是,没有办法使用边界框来计划paint-event,这意味着QGraphicsPixmapItem :: paint()被强制重新绘制整个QPixmap,因此在子类中重新实现此paint()方法可以无法仅部分更新QPixmap,因此对QPixmap进行较小的(本地)更新速度过慢,这是无法接受的。
这样的子类看起来像这样:
1 2 3 4 5 6 7 8 9 10 | 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,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //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(
在我提出解决方案之前,有几点想法:
首先,Graphics View框架旨在作为一种用于显示许多图形对象的解决方案,因此一个大图像并不是那么合适。当然,我知道您的示例可能只是人为的,因此这一点可能并不适用。其次,由于该框架非常以转换为中心,因此除非所有转换都是同一性,没有滚动等,否则仅重绘QGraphicsItem的一部分可能没有意义。
无论如何,如果只想绘制QGraphicsItem的一部分,则可以简单地存储需要更新的rect,然后从
1 2 3 4 5 6 7 8 9 10 | CustomItem::setPaintRect(const QRectF &rect) { paintRect = rect; update(); } CustomItem::paint(QPainter *painter /* etc. */) { painter->fillRect(paintRect, brush); } |