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_ ()

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Papageno
  • 305
  • 3
  • 15

1 Answers1

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.

musicamante
  • 41,230
  • 6
  • 33
  • 58
  • 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 Mar 22 '21 at 07:11
  • @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. – musicamante Mar 22 '21 at 12:15
  • 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. – Papageno Mar 23 '21 at 14:16
  • 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: – musicamante Mar 23 '21 at 14:41
  • 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; }`. – musicamante Mar 23 '21 at 14:42
  • Aah, that's mentioned in the docs, but I didn't catch its usability. Thanks. I'll build step by step some tools for css styling like I tried [here](https://stackoverflow.com/questions/63414417/how-to-calculate-gradients-for-css-with-same-angle-in-different-button-sizes) – Papageno Mar 23 '21 at 15:23