QPainter在QPixmap上绘制文本显示模糊问题求助
QPixmap绘制文本后显示模糊的原因与解决方法
问题描述
在QMainWindow的paintEvent中,直接绘制文本时显示效果清晰;但先将文本绘制到QPixmap,再复制到窗口时,文本(尤其是/字符)出现明显模糊。已启用QPainter::HighQualityAntialiasing渲染提示,且两种场景使用相同的窗口默认字体。
相关代码
mainwindow.hxx
#include "mainwindow.hxx" #include "./ui_mainwindow.h" #include <QPainter> #include <QString> #include <QStaticText> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); auto f = font(); f.setPixelSize(70); setFont(f); } MainWindow::~MainWindow() { delete ui; } void MainWindow::paintEvent(QPaintEvent *event) { { QPixmap img(width(), height()); QPainter painter(&img); painter.setFont(font()); painter.setBrush(Qt::black); painter.setPen(Qt::NoPen); painter.drawRect(rect()); painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setPen(Qt::blue); painter.drawText(0, 80, "/// lorem ipsum dolor sit amet"); // Create a QPainter to draw on the window QPainter painter2(this); painter2.setRenderHint(QPainter::HighQualityAntialiasing); painter2.drawPixmap(rect(), img); } { // Create a QPainter to draw on the window QPainter painter(this); painter.setFont(font()); painter.setBrush(Qt::black); painter.setPen(Qt::NoPen); painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setPen(Qt::blue); painter.drawText(0, 300, "/// lorem ipsum dolor sit amet"); } }
main.cxx
#include "mainwindow.hxx" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"/> </widget> <resources/> <connections/> </ui>
原因分析
核心问题是设备像素比(Device Pixel Ratio, DPR)不匹配:
- 直接绘制到窗口时,QPainter会自动适配系统的高DPI设置,使用窗口的设备像素比渲染文本,确保每个逻辑像素对应足够的物理像素,保证清晰度。
- 手动创建QPixmap时,默认使用1.0的设备像素比。在高分辨率屏幕(DPR>1)下,QPixmap的实际物理像素尺寸远小于窗口的物理像素尺寸,后续将其绘制到窗口时会被拉伸放大,导致文本边缘模糊,细节丢失(比如
/这类细线条字符)。 - 仅启用抗锯齿无法解决该问题,因为抗锯齿是优化渲染过程的平滑度,无法弥补物理像素不足的根源。
解决方案
创建QPixmap时,需匹配窗口的设备像素比,确保QPixmap的物理像素尺寸足够:
修改后的paintEvent代码
void MainWindow::paintEvent(QPaintEvent *event) { { // 获取窗口的设备像素比 qreal dpr = devicePixelRatio(); // 创建对应物理像素尺寸的QPixmap QPixmap img(width() * dpr, height() * dpr); // 设置QPixmap的设备像素比,与窗口保持一致 img.setDevicePixelRatio(dpr); QPainter painter(&img); painter.setFont(font()); painter.setBrush(Qt::black); painter.setPen(Qt::NoPen); // 绘制QPixmap自身的背景矩形(物理像素尺寸) painter.drawRect(img.rect()); painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setPen(Qt::blue); // 用逻辑坐标绘制文本,QPainter会自动转换为物理像素 painter.drawText(0, 80, "/// lorem ipsum dolor sit amet"); QPainter painter2(this); painter2.setRenderHint(QPainter::HighQualityAntialiasing); painter2.drawPixmap(rect(), img); } { QPainter painter(this); painter.setFont(font()); painter.setBrush(Qt::black); painter.setPen(Qt::NoPen); painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setPen(Qt::blue); painter.drawText(0, 300, "/// lorem ipsum dolor sit amet"); } }
关键说明
- 匹配DPR:通过
devicePixelRatio()获取窗口的设备像素比,以此创建对应物理像素尺寸的QPixmap,并设置其DPR,确保渲染的文本拥有足够的像素细节。 - 坐标适配:绘制文本时使用逻辑坐标即可,QPainter会根据QPixmap的DPR自动转换为物理像素,无需手动调整坐标值。
- 背景绘制:绘制QPixmap背景时,使用
img.rect()而非窗口的rect(),避免因尺寸不匹配导致的绘制异常。
内容的提问来源于stack exchange,提问作者overscore
相关产品推荐
相关产品推荐

