如何在pyqt中解决启用DPI缩放后QIcon模糊的问题

博客 动态
0 167
羽尘
羽尘 2022-05-11 20:59:08
悬赏:0 积分 收藏

如何在 pyqt 中解决启用 DPI 缩放后 QIcon 模糊的问题

问题描述

如今显示器的分辨率越来越高,如果不启用 DPI 缩放,软件的字体和图标在高分屏下就会显得非常小,看得很累人。从 5.6 版本开始,Qt 便能支持 DPI 缩放功能,Qt6 开始这个功能是默认开启的。

启用 DPI 缩放后,文字不会有太明显的锯齿问题,但是使用 QIcon 设置的图标却会显得很模糊。比如下述代码:

# coding:utf-8import osimport sysfrom PyQt5.QtGui import QIconfrom PyQt5.QtWidgets import QApplication, QPushButton, QWidgetclass Demo(QWidget):    def __init__(self):        super().__init__(parent=None)        self.resize(300, 300)        self.button = QPushButton(' Shuffle all', self)        self.button.setIcon(QIcon("Shuffle.png"))        self.button.move(self.width()//2-self.button.width()//2,                         self.height()//2-self.button.height()//2)if __name__ == '__main__':    os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "0"    os.environ["QT_SCALE_FACTOR"] = '1.25'    app = QApplication(sys.argv)    demo = Demo()    demo.show()    app.exec_()

运行结果如下图所示,可以看到图标的锯齿现象非常明显:

图标模糊

问题解决

QIcon 底层依靠 QIconEngine 来绘制图标,生成图标的 pixmap。猜测 QIconEngine 使用 QPainter 绘制图标时没有设置 QPainter.SmoothPixmapTransform 标志位,所以导致只缩放了图标,而没有进行平滑插值。为了解决这个问题,我们可以继承 QIconEngine,重写两个虚方法 paint()pixmap(),代码如下:

# coding:utf-8from PyQt5.QtCore import QPoint, QRect, QSize, Qtfrom PyQt5.QtGui import QIcon, QIconEngine, QImage, QPixmap, QPainterclass PixmapIconEngine(QIconEngine):    """ Pixmap icon engine """    def __init__(self, iconPath: str):        self.iconPath = iconPath        super().__init__()    def paint(self, painter: QPainter, rect: QRect, mode: QIcon.Mode, state: QIcon.State):        painter.setRenderHints(QPainter.Antialiasing |                               QPainter.SmoothPixmapTransform)        painter.drawImage(rect, QImage(self.iconPath))    def pixmap(self, size: QSize, mode: QIcon.Mode, state: QIcon.State) -> QPixmap:        pixmap = QPixmap(size)        pixmap.fill(Qt.transparent)        self.paint(QPainter(pixmap), QRect(QPoint(0, 0), size), mode, state)        return pixmapclass Icon(QIcon):    def __init__(self, iconPath: str):        self.iconPath = iconPath        super().__init__(PixmapIconEngine(iconPath))

接着只要把 QIcon 换成 Icon,并开启 app.setAttribute(Qt.AA_UseHighDpiPixmaps),就能解决图标模糊的问题了,效果如下图所示:

解决锯齿问题

posted @ 2022-05-11 20:11 之一Yo 阅读(12) 评论(1) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员