4

I am creating qpushbuttons with a certain style and then updating the style sheet to color them later on. However when I do this it overwrites the original style. Is there a way I can update or append to the object's stylesheet without losing it or having to redefine everything again?

import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout,QPushButton, QMenu, QApplication, QWidget, QInputDialog, QLineEdit
from PyQt5.QtCore import QSize, QCoreApplication, Qt, QLine, QPoint
from PyQt5.QtGui import QPainter, QPen, QFont,QPainter, QPainterPath, QPixmap


class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setMinimumSize(QSize(400, 400))   

        color = QPushButton('color', self)
        color.clicked.connect(self.color)
        color.resize(100,115)
        color.move(0, 100)

        buttons= ['button1','button2','button3']
        self.pybutton = {}
        x=0
        t = 0
        for i in buttons:
            t = t + 100
            x+=1
            self.pybutton[str(x)] = QPushButton(i, self) 
            self.pybutton[str(x)].setObjectName('btn' + str(x))
            self.pybutton[str(x)].resize(100,100)
            self.pybutton[str(x)].move(400-int(t),100)
            self.pybutton[str(x)].setStyleSheet('QPushButton {max-width: 75px;text-align:center;padding-left: 20px; max-height: 60px; font-size: 20px;}')
        self.statusBar()
    def status(self):
        sender = self.sender()
        print('PyQt5 button click')
        self.statusBar().showMessage(sender.text() + ' was pressed')

    def color(self):
        for i in self.pybutton:
            self.pybutton[str(i)].objectName()
            if self.pybutton[str(i)].objectName() == 'btn1':
                self.pybutton[str(i)].setStyleSheet("background-color: green")
            else:
                self.pybutton[str(i)].setStyleSheet("background-color: red")    

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
riyadude
  • 337
  • 6
  • 18

2 Answers2

4

A possible solution would be to have the stylesheet set with the styleSheet() method and then analyze the text and modify it as necessary but that can be very hard. Another better solution is to use the QSS Property Selector and choose the color by modifying a property:

import sys
from PyQt5.QtWidgets import QMainWindow,QPushButton, QApplication
from PyQt5.QtCore import QSize


class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setMinimumSize(QSize(400, 400))   

        color = QPushButton('color', self)
        color.clicked.connect(self.color)
        color.resize(100,115)
        color.move(0, 100)

        buttons= ['button1','button2','button3']
        self.pybutton = {}

        qss = """
        QPushButton{
            max-width: 75px;
            text-align:center;
            padding-left: 20px; 
            max-height: 60px; 
            font-size: 20px;
        }
        QPushButton[color = "0"]{
            background-color: green;
        }
        QPushButton[color = "1"]{
            background-color: red;
        }
        """

        for i, text in enumerate(buttons):
            btn = QPushButton(text, self) 
            btn.setObjectName('btn{}'.format(i))
            btn.setGeometry(300-i*100, 100, 100,100)
            btn.setStyleSheet(qss)
            self.pybutton[str(i)] = btn

    def color(self):
        for i, btn in self.pybutton.items():
            if btn.objectName() == 'btn1':
                btn.setProperty("color", "0")
            else:
                btn.setProperty("color", "1") 
            btn.style().polish(btn)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
0

This is a "hack" way to update style sheet, let's go straight to my code example.

class ButtonStyle:
    def __init__(self: QPushButton):
        self.setMinimumSize(self.sizeHint())

    @property
    def style_sheet(self) -> str:
        return self.styleSheet() + '\n'

    def set_bg_color(self, color: str):
        # name or hex str
        style = self.style_sheet \
                + """
                QPushButton#%s {
                    background-color: %s;
                }
                """ % (self.objectName(), color)

        self.setStyleSheet(style)

    def set_hover_bg_color(self, color: str):
        style = self.style_sheet \
                + """
                QPushButton#%s:hover{
                    background-color: %s;
                } 
                """ % (self.objectName(), color)

        self.setStyleSheet(style)

    def set_pressed_bg_color(self, color: str):
        style = self.style_sheet \
                + """
                QPushButton#%s:pressed {
                    background-color: %s;
                }
                """ % (self.objectName(), color)
        self.setStyleSheet(style)

    def set_border_radius(self, px: int):
        """set px radius
        """
        style = self.style_sheet \
                + """
                QPushButton#%s {
                    border-radius: %spx;
                }""" % (self.objectName(), px)
        self.setStyleSheet(style)


class Button(QPushButton, ButtonStyle):
    def __init__(self, *args, **kwargs):
        super(Button, self).__init__(*args, **kwargs)
        self.set_default_object_name()

    def set_default_object_name(self):
        """set default object name to :Class: Name
        """
        self.setObjectName(self.__class__.__name__)


class RedButton(Button):
    def __init__(self, *args, **kwargs):
        super(RedButton, self).__init__(*args, **kwargs)
        self.init_style()

    def init_style(self):
        self.set_bg_color('#f44336')
        self.set_hover_bg_color('#e57373')
        self.set_pressed_bg_color('#ffcdd2')
        self.set_border_radius(8)
        print(self.styleSheet())


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.widget = QWidget(self)
        self.setWindowTitle('Button Split Style')
        v_layout = QVBoxLayout()
        self.button = Button('NORMAL')
        self.red_button = RedButton('RED')
        v_layout.addStretch(1)
        v_layout.addWidget(self.button)
        v_layout.addWidget(self.red_button)
        v_layout.addStretch(1)

        self.widget.setLayout(v_layout)
        self.resize(500, 500)
        self.setCentralWidget(self.widget)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

The \n is to fromat style str. It works like "update" operation, the new style will override the same style defined before it.

tomy0608
  • 317
  • 1
  • 9