QGraphicsView::setRenderHint
有兩個常用的選項:QPainter::Antialiasing
和QPainter::SmoothPixmapTransform
,前者是用來打開反走樣功能,後者用來在對圖片進行縮放時啓用線性插值算法而不是最鄰近算法。然而這兩個選項都有一些坑,想達到預期的效果的話得做一些額外的功課。
QPainter::Antialiasing和QOpenGLWidget
如果viewport
被設置成了QOpenGLWidget
控件的話,想要啓用QPainter::Antialiasing
,那QOpenGLWidget
必須開啓多重採樣,否則反走樣效果完全不生效。畢竟OpenGL
默認的反走樣手段就是多重採樣(是否也是唯一的手段呢?),沒開多重採樣就沒反走樣很正常。不過這種情況下Qt
連個警告提示都不會給,這就有點坑了。不過這個坑在Qt
文檔Graphics View Framework
裏有提到,那就怪自己沒好好讀文檔吧。
如果viewport
被設置成QWidget
控件的話就沒這個問題了,用CPU反走樣有內存就可以了。
QPainter::SmoothPixmapTransform和QGraphicsPixmapItem
(這個比上面那個要坑。)如果沒有特別的需求,往場景裏面添加圖片用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
類。