Search code examples
pythonpython-3.xpyqtpyqt5qpushbutton

Button with 3 different options


Is there a way to have a button with 2 options? I want to have a button where on option one the button will change its color to red, on option two to yellow and on option 3 to green. Pressing again (a 4th time) will start from the beginning (red --> yellow --> green).

So far i am only able to set the button for 2 options, but the user of the destopapplication i made is supposed to have 3 options. Here is my code so far (fyi: the button is inside a QTableWidget, therefore the for x in range):

 for x in range(cell_num):
        self.button = QPushButton(' ',self)
        self.button.setFlat(True)
        self.table.setCellWidget(x, 5, self.button)  # lights_button

        self.button.clicked.connect(
            lambda state, w=self.table.cellWidget(x, 5), r=x, c=5: self.button_pushed(w, r, c)
        )



  def button_pushed(self, w, r, c):
        if w.text() != " ":
            w.setIcon(QIcon("..\image\green_button.png"))
            w.setText(" ")
        elif w.text() == "Likes/UnLikes/Normal":
            w.setIcon(QIcon("..\image\yellow_button.png"))
            w.setText(" Likes/Normal")
        else:
            w.setIcon(QIcon("..\image\darkred_button.png"))
            w.setText("  ")

Solution

  • You have to implement a state machine, in this case it is better to create a custom button.

    from itertools import cycle
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Button(QtWidgets.QPushButton):
        RedState, YellowState, GreenState = range(3)
    
        def __init__(self, *args, **kwargs):
            super(Button, self).__init__(*args, **kwargs)
            self._current_state = Button.RedState
            self._states = cycle([Button.RedState, Button.YellowState, Button.GreenState])
            self.on_clicked()
            self.clicked.connect(self.on_clicked)
    
        def update_button(self):
            if self._current_state == Button.RedState:
                self.setIcon(QtGui.QIcon(r"..\image\green_button.png"))
                self.setText(" ")
            elif self._current_state == Button.YellowState:
                self.setIcon(QtGui.QIcon(r"..\image\yellow_button.png"))
                self.setText(" Likes/Normal")
            elif self._current_state == Button.GreenState:
                self.setIcon(QtGui.QIcon(r"..\image\darkred_button.png"))
                self.setText("  ")
    
        @QtCore.pyqtSlot()
        def on_clicked(self):
            self._current_state = next(self._states)
            self.update_button()
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            self.table = QtWidgets.QTableWidget(10, 10)
            self.setCentralWidget(self.table)
    
            for x in range(self.table.rowCount()):
                button = Button(flat=True)
                self.table.setCellWidget(x, 5, button)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())