0

I try to set the background color of pushButton.checked(). It works fine if the button is enabled and pushButton.checked() == False, it sets the background color to disabled color of styleSheet() But if the button is disabled and the pushButton.checked() == True it doesn't change the background color. I've tried the workarounds in this post, without luck. Some others are close to the posts links.

The example below: Use lower button to enable(disable the upper and use the upper button to set it checked/unchecked and enable/disable it with the lower one to see what I mean. The background should always gray it the button is disabled.

Is there a special setting or combination required?

import sys

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setMinimumSize(300,300)
        self.pushButton1 = QPushButton("see css result", self)
        self.pushButton1.setCheckable(True)
        #self.pushButton1.setAutoFillBackground (True)    # mentioned in
        self.pushButton1.setStyleSheet(css_pushButton())
        self.pushButton1.resize (100, 40)
        self.pushButton1.move(50,50)
        print("scc1:", self.pushButton1.styleSheet())

        self.pushButton_control = QPushButton("Button Enabled", self)
        self.pushButton_control.setCheckable(False)
        self.pushButton_control.clicked.connect(self.pushButton_control_clicked)
        self.pushButton_control.move(50,100)
        self.pushButton_control.resize (100, 40)

    def pushButton_control_clicked(self):
        print("Checked:",self.pushButton1.isChecked())
        if self.pushButton1.isEnabled():
            print("set False")
            self.pushButton1.setEnabled(False)
            self.pushButton_control.setText(('DISABLED'))
        else:
            self.pushButton1.setEnabled(True)
            self.pushButton_control.setText(('ENABLED'))
            print("set True")


def css_pushButton():
    css = '''
            QPushButton {
                            font-size: 10px;
                            background-color: green;
                            color: black;
                            border: 2px green;
                            border-radius: 22px;
                            border-style: outset;
                                }
            QPushButton:hover {
                            background: qradialgradient(
                                cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,
                                radius: 1.35, stop: 0 grey, stop: 1 lightgray
                                );
                            }
            QPushButton:enabled{
                            color: black;
                            font:  10px;
                            background: green;
                            background-color: red;
                            border: 1px black;
                            border-style: outset;
                            }
            QPushButton:pressed {
                            color: white;
                            background: yellow;
                            }
            QPushButton:disabled {
                            color: gray;
                            background-color: gray;
                            border: 1px black;
                            border-style: outset;                
                        }
            QPushButton:checked{
                        color: black; 
                        font:  12px;   
                        font: bold;
                        background-color: red;
                        border: 1px black;
                        border-style: outset;
                        }
            QPushButton:!checked{
                        color: black; 
                        font:  12px;   
                        font: bold;
                        background-color: green;
                        border: 1px black;
                        border-style: outset;
            }
            
                '''
    return css

if __name__ == "__main__":
    app = QApplication (sys.argv)
    prog = MainWindow()
    prog.show ()
    app.exec_ ()

1 Answer 1

3

Even in OOP the order of declarations of objects and properties is important, as the last takes precedence on the previous. This is valid for stylesheets too.

In your code, the :checked and :!checked rules take precedence ("override") over any property declared before, which includes what specified in :disabled.

The solution is simple: move the :disabled block at the end.

Even better, use combined selectors:

            QPushButton:disabled {
                        color: gray;
            }
            QPushButton:disabled:checked {
                        background-color: #ffaaaa;
            }
            QPushButton:disabled:!checked {
                        background-color: lightGreen;
            }

Read more about stylesheet conflict resolution on the Qt docs.

Sign up to request clarification or add additional context in comments.

6 Comments

I thought that disabled and all other keys are separate properties and do not depend on each other so I didn't take care on it. But the combination is very useful and this I didn't use until now.
@Papageno consider this stylesheet: QWidget { background: green; } QWidget { background: red; }. It's a valid syntax, but what color would the background have? A stylesheet is a system to override object properties, in cascade: any selector is used to set more specific properties, while inheriting the default ones if not explicitly specified. It works like that for standard stylesheets, and Qt just implemented the same behavior.
It looks simple and sounds logical. But where is the definition for sequencing? As in my example mentioned it may be !checked > checked > disabled > pressed > enabled > hover > basic settings. In my expirience it't the best to fill all used parameter : values; but I'm still looking for the hierarchy. I think the hierarchy is made by the structure of css, but how does it rise internally? Your mentioned background should be red if I'm right.
Setting all properties for each selector (including subcontrols and pseudo states) is not always a good thing. First of all, you'll probably end up by writing lots of unnecessary code (for instance, your border is almost always 1px black); then you'll overwrite properties that depend on other selectors: setting the border on the checked pseudo state overrides any border set for any other pseudo state set before, whenever the widget is checked. Yes, in the example of my previous comment, the result is that the background would be red. Remember that you can also use properties as selectors:
For instance, if you want to always have border: 2px green; for normal clickable buttons, but border: 1px black; for checkable buttons, then you can use QPushButton { border: 2px green; } QPushButton[checkable="true"] { border: 1px black; }.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.