Search code examples
pythonpysidestylesheetqpushbutton

How do I apply checkable stylesheet properties to multiple QPushButtons with PySide?


I'm on an Linux box (Ubuntu 16.04) with Python 3.5 and PySide 1.2.2.

If I have QPushButtons that are not checkable, and I only set the style sheet once, the buttons appear the way that I would like. However, if I make them checkable, Qt wants to play with focused and unfocused style, prioritizing those over what I'd asked for.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import os

from PySide.QtCore import *
from PySide.QtGui  import *

class UI(QDialog):

    def __init__(self, *args, **kwargs):
        super(UI, self).__init__(**kwargs)

        outerBox = QGroupBox(self)
        outerBox.setGeometry(50, 50, 200, 150)
        outerBox.setObjectName("outerBox")

        brokenCss  = "QPushButton:unchecked {"
        brokenCss += "  background-color:  #ce9a9a;"  # red-ish
        brokenCss += "  border: 1px outset #000000;"
        brokenCss += "  border-radius: 6px;"
        brokenCss += "}"
        brokenCss += "QPushButton:checked {"
        brokenCss += "  background-color:  #12f785;"  # green-ish
        brokenCss += "  border: 1px inset  #000000;"
        brokenCss += "  border-radius: 6px;"
        brokenCss += "}"

        broken = []
        for i in range(2):
            broken.append(QPushButton(outerBox))
            broken[i].setObjectName("broken{0}".format(i))
            broken[i].setGeometry(15, (35 * (i + 1)), 100, 20)
            broken[i].setText("Broken CSS {0}".format(i))
            broken[i].setCheckable(True)
            broken[i].setChecked(False)
            broken[i].setStyleSheet(brokenCss)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = UI()
    ui.showFullScreen()
    sys.exit(app.exec_())

I was hoping the above would produce two red-ish buttons at startup, which would then turn green-ish and remain green-ish once they have been pressed once (and flip back to red-ish when clicked again). Instead I see:

A focused button and an unfocused button

Once they are both clicked they each turn green, though most recently clicked is slightly darker, indicating focus, I guess. But toggling them back to off gives me the image above again, instead of two red buttons.

I have tried adding CSS "stanzas" for :default, :flat and several other pseudo-states, all to no avail.


Solution

  • Apparently, the documentation does not match reality. unchecked and checked were the documented way to do what I wanted, but after experimenting with off and on which were equally ineffective, I tried closed and open, which, as I understand from the documentation, is only supposed to apply to QPushButtons with menus attached. Nonetheless, that worked. (It doesn't seem to be doing the outset and inset but it's getting the colors right.)

    I also switched to PyQt5 to see if there would be a change, but it behaved the same as PySide.

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import sys
    import os
    
    from PySide.QtCore import *
    from PySide.QtGui  import *
    
    class UI(QDialog):
    
        def __init__(self, *args, **kwargs):
            super(UI, self).__init__(**kwargs)
    
            outerBox = QGroupBox(self)
            outerBox.setGeometry(50, 50, 200, 150)
            outerBox.setObjectName("outerBox")
    
            brokenCss  = "QPushButton:closed {"
            brokenCss += "  background-color:  #ce9a9a;"  # red-ish
            brokenCss += "  border: 1px outset #000000;"
            brokenCss += "  border-radius: 6px;"
            brokenCss += "}"
            brokenCss += "QPushButton:open {"
            brokenCss += "  background-color:  #12f785;"  # green-ish
            brokenCss += "  border: 1px inset  #000000;"
            brokenCss += "  border-radius: 6px;"
            brokenCss += "}"
    
            broken = []
            for i in range(2):
                broken.append(QPushButton(outerBox))
                broken[i].setObjectName("broken{0}".format(i))
                broken[i].setGeometry(15, (35 * (i + 1)), 100, 20)
                broken[i].setText("Broken CSS {0}".format(i))
                broken[i].setCheckable(True)
                broken[i].setChecked(False)
                broken[i].setStyleSheet(brokenCss)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ui = UI()
        ui.showFullScreen()
        sys.exit(app.exec_())