Python 如何更改QPalette的当前颜色组

Python 如何更改QPalette的当前颜色组,python,windows,qt,pyside,qpalette,Python,Windows,Qt,Pyside,Qpalette,我试图更改Qpalete的当前颜色组,但Qpalete的setCurrentColorGroup方法似乎根本不起作用 我正在运行以下代码: app = QtGui.QApplication(sys.argv) button = QPushButton() svgWidget = QSvgWidget(resources_paths.getPathToIconFile("_playableLabels/42-labelPlay-disabled-c.svg")) button.setLayou

我试图更改Qpalete的当前颜色组,但Qpalete的setCurrentColorGroup方法似乎根本不起作用

我正在运行以下代码:

app = QtGui.QApplication(sys.argv)

button = QPushButton()
svgWidget = QSvgWidget(resources_paths.getPathToIconFile("_playableLabels/42-labelPlay-disabled-c.svg"))

button.setLayout(QHBoxLayout())
button.layout().addWidget(svgWidget)

button.setFixedSize(QSize(300, 300))

print button.palette().currentColorGroup()
button.setEnabled(False)
print button.palette().currentColorGroup()
button.palette().setCurrentColorGroup(QPalette.ColorGroup.Normal)
print button.palette().currentColorGroup()
button.show()
print button.palette().currentColorGroup()

app.exec_()
这是我得到的输出:

PySide.QtGui.QPalette.ColorGroup.Normal
PySide.QtGui.QPalette.ColorGroup.Disabled
PySide.QtGui.QPalette.ColorGroup.Disabled
PySide.QtGui.QPalette.ColorGroup.Disabled

Process finished with exit code -1
所以。。。似乎setCurrentColorGroup什么都不做。关于如何更改当前的颜色组,有什么想法吗

提前谢谢


(顺便说一句,我正在Windows 7系统上运行PySide 1.2.4和Qt 4.8)

您似乎试图更改图标的呈现方式,而不是小部件的绘制方式,因此调色板不是正确的API。相反,您应该使用,它允许不同的图像用于不同的和

要在
正常
禁用
模式下使用相同的图像,请使用如下代码:

icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap('image.svg'), QtGui.QIcon.Normal)
icon.addPixmap(QtGui.QPixmap('image.svg'), QtGui.QIcon.Disabled)
button = QtGui.QPushButton()
button.setIcon(icon)
palette = self.button.palette()
palette.setCurrentColorGroup(QtGui.QPalette.Normal)
palette.setColorGroup(QtGui.QPalette.Disabled,
    palette.windowText(), palette.button(),
    palette.light(), palette.dark(), palette.mid(),
    palette.text(), palette.brightText(),
    palette.base(), palette.window(),
    )
button.setPalette(palette)
但是,您应该注意Qt文档中的警告:

自定义图标引擎可以自由忽略额外添加的像素贴图

因此,不能保证这将适用于所有平台上的所有小部件样式

更新

如果上述方法不起作用,则可能意味着小部件样式正在控制禁用图标的呈现方式。相关的
QStyle
API是,它返回根据和样式选项修改的pixmap的副本。似乎这个方法有时也会考虑调色板(与我上面所说的有些相反),但是当我测试这个方法时,它没有任何影响。我按如下方式重置调色板:

icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap('image.svg'), QtGui.QIcon.Normal)
icon.addPixmap(QtGui.QPixmap('image.svg'), QtGui.QIcon.Disabled)
button = QtGui.QPushButton()
button.setIcon(icon)
palette = self.button.palette()
palette.setCurrentColorGroup(QtGui.QPalette.Normal)
palette.setColorGroup(QtGui.QPalette.Disabled,
    palette.windowText(), palette.button(),
    palette.light(), palette.dark(), palette.mid(),
    palette.text(), palette.brightText(),
    palette.base(), palette.window(),
    )
button.setPalette(palette)
这使得按钮被禁用时颜色看起来正常,但图标仍然是灰色的。尽管如此,您可能还是想尝试一下,以防在您的平台上出现不同的情况(如果没有,请不要感到惊讶)

控制图标禁用的正确方法似乎是创建
QProxyStyle
并覆盖
generatedIconPixmap
方法。不幸的是,这个类在PyQt4中不可用,但我已经在PyQt5中对它进行了测试,它可以工作。因此,目前唯一可行的解决方案是升级到PyQt5,并使用
QProxyStyle
。下面是演示如何实现它的演示脚本:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class ProxyStyle(QtWidgets.QProxyStyle):
    def generatedIconPixmap(self, mode, pixmap, option):
        if mode == QtGui.QIcon.Disabled:
            mode = QtGui.QIcon.Normal
        return super(ProxyStyle, self).generatedIconPixmap(
            mode, pixmap, option)

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.button = QtWidgets.QPushButton(self)
        self.button.setIcon(QtGui.QIcon('image.svg'))
        self.button2 = QtWidgets.QPushButton('Test', self)
        self.button2.setCheckable(True)
        self.button2.clicked.connect(self.button.setDisabled)    
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.button)
        layout.addWidget(self.button2)

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle(ProxyStyle())
    window = Window()
    window.setGeometry(600, 100, 300, 200)
    window.show()
    sys.exit(app.exec_())

palete()
方法是
const&
——也就是说,在python术语中,它返回一个副本,而不是一个引用。因此,您需要修改返回的调色板,然后使用
按钮。setPalette(调色板)
应用更改。但是,使用
setCurrentColorGroup
仍然不太可能有任何效果,因为该按钮仍将被禁用。此外,您还需要注意,某些样式不会对所有类型的图形使用调色板(这主要影响某些版本的Windows和OSX)。也许你应该解释一下用这种方式使用调色板想要达到什么目的。@ekhumoro我得到了一个按钮(QPushButton的一个平面无边界子类),它使用svg作为图标。源svg有一个红色背景,当我禁用按钮时,背景变成灰色。我不希望图标颜色被扭曲。我不知道禁用按钮时按钮是如何改变颜色的,但我发现它应该与调色板有关,所以我尝试将调色板的currentColorGroup设置为正常(而不是禁用),但它没有任何作用…@ekhumoro我使用的是PySide,所以我没有常量变量或指针之类的东西。我验证了每次调用button.palette()都会得到相同的Qpalete实例,但这可能只是一个包装器?我将按照您的建议尝试使用setPalette()。@ekhumoro它也不起作用。。。事实上,创建一个Qpalete,然后在其上使用setCurrentColorGroup也没有任何作用。我发现这真的很有意思:/NO,你通过Python使用Qt,所以C++签名总是相关的。如果您不理解这一关键点,就永远无法有效地使用PySide/PyQt。在Python中,修改一个可变对象(如列表)的副本,不会修改原始- C++并没有什么不同。因此,如果Qt方法返回一个
常量&
,那么在PySide中,您将获得一个副本;但是如果它返回一个指针,你就得到了原始的。PySead只是一个围绕C++库的薄包装。调用PySide方法总是调用Qt中完全相同的方法。您好!我正是这样使用QIcon的:
cls.PlayEnabledIcon=QIcon(resources\u path.getPathToIconFile(“\u playelabels/42 labelPlay enabled.svg”))cls.PlayEnabledIcon.addFile(resources\u path.getPathToIconFile(“\u playelabellable-disabled-c.svg”),mode=QIcon.disabled)
我的红色图标仍呈现为灰色。@GuillermoAres。正如我所说:“不能保证这将适用于所有平台上的所有小部件样式”。我在我的答案中添加了更多的信息,建议可能的解决方法。我读到了,但我知道事实上它并没有忽略我为
QIcon.Disabled
模式添加的文件,因为它与我为
QIcon.Normal
设置的文件有很大不同(首先是“播放”)三角形,另一个是感叹号)。禁用时,它确实会显示感叹号,但会将问号的颜色从红色更改为灰色。我见过Qt自动改变禁用按钮图标的颜色,这就是为什么我认为它可能与调色板有关,但可能是引擎本身。对我来说太晦涩了。谢谢你的耐心!:)顺便说一句,我真的不知道该怎么处理这个问题。有点乱。既然你在这方面似乎比我更有经验。。。我应该把你的答案标记为正确吗?