【问题标题】:PyQt5 Fusion Style Button Icons are brokenPyQt5 Fusion Style Button Icons 坏了
【发布时间】:2020-12-21 03:09:18
【问题描述】:

我想要一个切换按钮来根据切换状态显示不同的图像。该功能在默认的 QApplication 样式('WindowsVista')下运行良好。但是 WindowsVista 风格很丑,我宁愿使用 Fusion 风格。不幸的是,图像在 Fusion Style 中没有改变。

代码:

from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton,
                             QStyleFactory, QLabel)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QSize
from PyQt5 import Qt, QtCore
import sys

class Test(QMainWindow):
    def __init__(self, parent=None):
        super(Test, self).__init__(parent=parent)
        self.setGeometry(50,50,300,400)
        
        icon = QIcon()
        icon.addFile('red.png', state = QIcon.Off)
        icon.addFile('green.png', state = QIcon.On)
        button = QPushButton(parent = self)
        button.setCheckable(True)
        button.setIcon(icon)
        button.setIconSize(QSize(150,150))
        button.setGeometry(50,50,200,200)
        
        verString = 'PyQt version: ' + Qt.PYQT_VERSION_STR + '\n'
        verString += 'Qt version: ' + QtCore.qVersion()
        print(verString)
        label = QLabel(verString, parent = self)
        label.setGeometry(50, 250, 200, 150)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    #app.setStyle(QStyleFactory.create('fusion'))
    app.setStyle(QStyleFactory.create('windowsvista'))
    test = Test()        
    test.show()
    sys.exit(app.exec_() )

WindowsVista 风格(左上按钮,右下按钮):

融合风格(左上按钮,右下按钮):

【问题讨论】:

    标签: python pyqt pyqt5 qstyle


    【解决方案1】:

    由于source code 中看到的融合风格,这似乎是一种默认行为:

    # ...
    case CE_PushButtonLabel:
        if (const QStyleOptionButton *button = qstyleoption_cast(option)) {
            QStyleOptionButton b(*button);
            // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style
            b.state &= ~(State_On | State_Sunken);
            QCommonStyle::drawControl(element, &b, painter, widget);
        }
        break;
    // ...

    一种可能的解决方案是实现一个覆盖此行为的 QProxyStyle:

    import sys
    
    from PyQt5.QtCore import QSize, qVersion, PYQT_VERSION_STR
    from PyQt5.QtGui import QIcon
    from PyQt5.QtWidgets import (
        QApplication,
        QMainWindow,
        QPushButton,
        QStyleFactory,
        QLabel,
        QProxyStyle,
        QStyle,
        QCommonStyle,
    )
    
    
    class ProxyStyle(QProxyStyle):
        def drawControl(self, control, option, painter, widget):
            if control == QStyle.CE_PushButtonLabel:
                QCommonStyle.drawControl(self, control, option, painter, widget)
            else:
                super().drawControl(control, option, painter, widget)
    
    
    class Test(QMainWindow):
        def __init__(self, parent=None):
            super(Test, self).__init__(parent=parent)
            self.setGeometry(50, 50, 300, 400)
    
            icon = QIcon()
            icon.addFile("red.png", state=QIcon.Off)
            icon.addFile("green.png", state=QIcon.On)
            button = QPushButton(parent=self)
            button.setCheckable(True)
            button.setIcon(icon)
            button.setIconSize(QSize(150, 150))
            button.setGeometry(50, 50, 200, 200)
    
            verString = "PyQt version: " + PYQT_VERSION_STR + "\n"
            verString += "Qt version: " + qVersion()
            print(verString)
            label = QLabel(verString, parent=self)
            label.setGeometry(50, 250, 200, 150)
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        app.setStyle(QStyleFactory.create("fusion"))
        proxy = ProxyStyle(app.style())
        app.setStyle(proxy)
        test = Test()
        test.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 不错的答案。谢谢。
    猜你喜欢
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 2017-08-12
    相关资源
    最近更新 更多