QGraphicsView::setRenderHint
有两个常用的选项:QPainter::Antialiasing
和QPainter::SmoothPixmapTransform
,前者是用来打开反走样功能,后者用来在对图片进行缩放时启用线性插值算法而不是最邻近算法。然而这两个选项都有一些坑,想达到预期的效果的话得做一些额外的功课。
如果viewport
被设置成了QOpenGLWidget
控件的话,想要启用QPainter::Antialiasing
,那QOpenGLWidget
必须开启多重采样,否则反走样效果完全不生效。毕竟OpenGL
默认的反走样手段就是多重采样(是否也是唯一的手段呢?),没开多重采样就没反走样很正常。不过这种情况下Qt
连个警告提示都不会给,这就有点坑了。不过这个坑在Qt
文档Graphics View Framework
里有提到,那就怪自己没好好读文档吧。
如果viewport
被设置成QWidget
控件的话就没这个问题了,用CPU反走样有内存就可以了。
(这个比上面那个要坑。)如果没有特别的需求,往场景里面添加图片用QGraphicsScene::addPixmap
就可以,这个方法会创建一个QGraphicsPixmapItem
,然后添加到场景里面。
当我们放大场景时,已添加的图片也会跟着放大,这就涉及到一个问题:使用哪种插值算法进行放大?默认情况下使用的是最邻近算法,放大后会有马赛克效果。如果我们希望线性插值算法来使图像平滑一些,该怎么做呢?QGraphicsView
的文档里面提到了QPainter::SmoothPixmapTransform
,能够改变默认的插值算法。然而实际情况是,如果使用QGraphicsScene::addPixmap
这种方式插入图片的话,这个选项是无效的!因为QGraphicsPixmapItem
有另外一个属性transformationMode
,QGraphicsPixmapItem
放大时的插值算法由这个属性决定,完全不受QPainter::SmoothPixmapTransform
的影响。QGraphicsPixmapItem::paint
是这么实现的:
void QGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_D(QGraphicsPixmapItem);
Q_UNUSED(widget);
painter->setRenderHint(QPainter::SmoothPixmapTransform,
(d->transformationMode == Qt::SmoothTransformation));
painter->drawPixmap(d->offset, d->pixmap);
if (option->state & QStyle::State_Selected)
qt_graphicsItem_highlightSelected(this, painter, option);
}
不管传入的painter
的renderHint
是什么,都会被覆盖掉。那这样的话QPainter::SmoothPixmapTransform
就形同虚设了,除非自己实现一个管理图片的QGraphicsItem
类。