Qt6中DPI设为125%时QLabel内QPixmap显示模糊问题
问题描述
我正在使用Qt6,通过QPixmap在QLabel中绘制一张PNG图片,并将像素图调整至适配QLabel的尺寸。当DPI设置为100%时,显示效果正常;但在笔记本电脑(默认推荐DPI为125%,用于放大文字)上,像素图显示模糊(线条发虚)。
相比之下,将同一张PNG图片设置为QPushButton的图标时,显示效果却正常。
请问我哪里操作有误?如何修改代码才能让QLabel中的图片显示效果与QPushButton中的一样清晰?
完整代码
mainwindow.cpp
#include "mainwindow.h" #include <QVBoxLayout> #include <QHBoxLayout> #include <QPushButton> #include <QApplication> #include <QLabel> MainWindow::MainWindow( QWidget* parent ) : QMainWindow(parent) { QWidget* centralWidget = new QWidget(this); centralWidget->setLayout(new QVBoxLayout(centralWidget)); QPushButton* button = new QPushButton(centralWidget); button->setIcon(QIcon(":/qtbug_pixmapscale/image.png")); QWidget* labelsWidget = new QWidget(centralWidget); labelsWidget->setLayout(new QHBoxLayout(labelsWidget)); QLabel* titleLabel = new QLabel(centralWidget); titleLabel->setText("This is ugly:"); QLabel* iconLabel = new QLabel(centralWidget); int maxHeight = titleLabel->sizeHint().height() + 10; iconLabel->setMaximumSize( QSize(maxHeight,maxHeight) ); iconLabel->setPixmap(QPixmap(":/qtbug_pixmapscale/image.png").scaled(iconLabel->maximumSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); labelsWidget->layout()->addWidget(titleLabel); labelsWidget->layout()->addWidget(iconLabel); centralWidget->layout()->addWidget(button); centralWidget->layout()->addWidget(labelsWidget); setCentralWidget(centralWidget); }
main.cpp
#include <QApplication> #include "mainwindow.h" // Qtbug where QPixmap drawn in a QLabel looks ugly on laptop when display is set to 125% int main( int argc, char* argv[] ) { QApplication app(argc, argv); MainWindow wnd; wnd.show(); return app.exec(); }
mainwindow.h
#pragma once #include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget* parent = NULL); };
pixmapscale.qrc
<RCC> <qresource prefix="/qtbug_pixmapscale"> <file>image.png</file> </qresource> </RCC>
(注:image.png为带线条的图标,在高DPI下QLabel显示模糊)
问题原因及解决方法
原因分析
问题出在直接使用设备无关的逻辑像素尺寸(widget的maximumSize)缩放QPixmap,未考虑Qt的高DPI缩放因子。QPushButton的setIcon会自动根据当前屏幕的设备像素比(DPR)处理图标,而手动调用scaled时用的是widget的逻辑像素尺寸,未转换为实际物理像素尺寸,导致缩放后的像素图分辨率不足,在高DPI屏幕上被拉伸后出现模糊。
解决方法
有两种可靠的修复方式:
方法一:手动处理设备像素比
在缩放QPixmap时,先获取屏幕的设备像素比,将逻辑尺寸转换为物理像素尺寸后再缩放:
QLabel* iconLabel = new QLabel(centralWidget); int maxHeight = titleLabel->sizeHint().height() + 10; iconLabel->setMaximumSize( QSize(maxHeight,maxHeight) ); // 获取当前屏幕的设备像素比 qreal dpr = qApp->primaryScreen()->devicePixelRatio(); // 将逻辑尺寸转换为物理像素尺寸 QSize actualSize = iconLabel->maximumSize() * dpr; // 按物理像素尺寸缩放,并设置设备像素比 QPixmap pixmap(":/qtbug_pixmapscale/image.png"); pixmap = pixmap.scaled(actualSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); pixmap.setDevicePixelRatio(dpr); iconLabel->setPixmap(pixmap);
方法二:让QLabel自动处理缩放(推荐)
无需手动缩放QPixmap,开启QLabel的scaledContents属性,让其自动根据自身尺寸和DPI适配图片:
QLabel* iconLabel = new QLabel(centralWidget); int maxHeight = titleLabel->sizeHint().height() + 10; iconLabel->setMaximumSize( QSize(maxHeight,maxHeight) ); // 开启自动缩放适配 iconLabel->setScaledContents(true); // 直接设置原始QPixmap,QLabel会自动处理高DPI缩放 iconLabel->setPixmap(QPixmap(":/qtbug_pixmapscale/image.png"));
这种方法更简洁,效果与QPushButton的图标显示逻辑一致。
额外说明
- Qt6默认启用高DPI支持,但手动操作QPixmap时需区分逻辑像素(widget使用的尺寸)和物理像素(屏幕实际像素点),两者的比值即为设备像素比(DPR)。
- QIcon内部会自动管理不同DPI下的资源适配,而QPixmap需要手动处理DPR才能保证高DPI清晰度。
内容的提问来源于stack exchange,提问作者jpo38
相关产品推荐
相关产品推荐

