'The icon of QPushButton is blurry when DPI scaling is enabled

I found the icon of QPushButon is blurry when DPI scaling is enabled. Even if replaced by SVG, the icon is still blurred. Is there any way to make the icon clearer?

Here is the code:

# coding:utf-8
import os
import sys

from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget


class Demo(QWidget):

    def __init__(self):
        super().__init__(parent=None)
        self.button = QPushButton(' Shuffle all', self)
        imagePath = "app/resource/images/random_play_all/Shuffle_normal.png"
        self.button.setIcon(QIcon(imagePath))
        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_()

The running result is shown in the figure below

running result



Solution 1:[1]

I solved this problem by rewriting QIconEngine and setting Qt.AA_UseHighDpiPixmaps flag.

# coding:utf-8
import os
import sys

from PyQt5.QtCore import QPoint, QRect, QSize, Qt
from PyQt5.QtGui import QIcon, QIconEngine, QImage, QPainter, QPixmap
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget



class 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 pixmap


class Icon(QIcon):

    def __init__(self, iconPath: str):
        self.iconPath = iconPath
        super().__init__(PixmapIconEngine(iconPath))


class Demo(QWidget):

    def __init__(self):
        super().__init__(parent=None)
        self.button = QPushButton(' Shuffle all', self)
        imagePath = "resource/images/random_play_all/Shuffle_normal.png"
        self.button.setIcon(Icon(imagePath))
        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'
    QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    app.exec_()

Here is the result

result

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 zhiyi