本文记录在使用 QPixmap 时容易感到困惑和犯错的地方,方便自己查阅,亦希望能成人之美。

1. QPixmap 成员函数

  • QPixmap::size() 值与程序的 devicePixelRatio 无关,输出的是图片原始尺寸。
  • AspectRatioMode 取值:
    • Qt::IgnoreAspectRatio 忽略图片原长宽比,将图片缩放到指定尺寸
    • Qt::KeepAspectRatio 在保持图片原长宽比和图片所有元素的情况下,尽量填充满目标矩形。
    • Qt::KeepAspectRatioByExpanding 在保持长宽比的情况下,拉伸图片保证填充满目标矩形,可能会舍弃部分图片元素。

  • scaledToWidth、scaledToHeight 函数可以实现在保持原图片长宽比的前提下,将图片缩放到指定的宽或者高。
  • drawPixmap 函数的参数从左到右依次是:目标区域 -> pix -> 源区域。目标区域会考虑当前 Widget 的 devicePixelRatio,而源区域则与 devicePixelRatio 无关。

2. 开启程序 DPI 缩放

1
2
3
4
5
    QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif

3. QPixmap::devicePixelRatio

首先 QPixmap::devicePixelRatio 仅适用于开启了 DPI 缩放的程序。

高分辨率版本的图片有大于 1 的设备像素比(即QPixmap::devicePixelRatio),如果该值匹配底层 QPaintDevice 的值,它将直接绘制到设备上,而不应用额外的转换。

该值用于指定当前 QPixmap 图片是基于 1 倍图的几倍缩放图。

需要注意的是,在使用drawPixmap函数时,如果该目标区域参数未指定宽和高,QPixmap::devicePixelRatio 才生效。

如下面的 drawPixmap 原型:

1
2
3
4
5
6
7
void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap, int sx, int sy, int sw, int sh)
void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap, const QRectF &source)
void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap, const QRect &source)
void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)

示例(程序已开启 DPI 缩放):

1
2
3
4
5
6
7
8
9
10
11
12
void QtWidgetsApplication1::paintEvent(QPaintEvent* e)
{
qDebug() << this->devicePixelRatioF(); // 当前程序的DPI缩放为1.5
QPainter painter(this);
QPixmap pix("D:\\gril.png"); // gril.png图片实际尺寸为400*400

// 告知程序该图片是基于1倍图进行4倍放大后的,即1倍图为宽高为400/4
pix.setDevicePixelRatio(4);

// 实际绘制的图片宽度为150*150,左上角坐标为150*150
painter.drawPixmap(QPoint(100,100), pix);
}


限于政策原因,在您看到该文章时,博客可能已经关闭了评论功能🥺

您可以通过在 blog-comment 项目中提交Issue来间接地发表评论🍀