4

I am new to PyQT5 and I want to have several buttons and have the one clicked last in a "checked" state. When another button is clicked the previous one gets "unchecked" while the clicked one gets "checked".

import sys
from PyQt5.QtWidgets import *

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(30, 30, 400, 200)
        self.initUI()

    def initUI(self):
        self.button1 = QPushButton(self)
        self.button1.setGeometry(40, 40, 100, 50)
        self.button1.setText("Button 1")

        self.button2 = QPushButton(self)
        self.button2.setGeometry(150, 40, 100, 50)
        self.button2.setText("Button 2")

        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Johan
  • 863
  • 3
  • 13
  • 28

3 Answers3

6

You can use functools partial or the sender method to check which button was pressed:

import sys
from PyQt5.QtWidgets import *
from functools import partial
class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(30, 30, 400, 200)
        self.initUI()

    def initUI(self):
        self.button1 = QPushButton(self)
        self.button1.setGeometry(40, 40, 100, 50)
        self.button1.setText("Button 1")
        self.button1.clicked.connect(partial(self.clicked_btn, 'Button 1'))

        self.button2 = QPushButton(self)
        self.button2.setGeometry(150, 40, 100, 50)
        self.button2.setText("Button 2")
        self.button2.clicked.connect(partial(self.clicked_btn, 'Button 2'))

        self.show()

    def clicked_btn(self, value):
        print(f'{value} clicked')
        sender = self.sender()
        print(f'Sender says: {sender.text()} was clicked')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
teresa a
  • 86
  • 1
  • 2
5

Building off of your code, you can add button1 and button2 to a QButtonGroup with the exclusive property set to True.

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(30, 30, 400, 200)
        self.initUI()

    def initUI(self):
        self.button1 = QPushButton(self)
        self.button1.setGeometry(40, 40, 100, 50)
        self.button1.setText("Button 1")

        self.button2 = QPushButton(self)
        self.button2.setGeometry(150, 40, 100, 50)
        self.button2.setText("Button 2")

        self.btn_grp = QButtonGroup()
        self.btn_grp.setExclusive(True)
        self.btn_grp.addButton(self.button1)
        self.btn_grp.addButton(self.button2)

        self.btn_grp.buttonClicked.connect(self.on_click)

        self.show()

    def on_click(self, btn):
        pass # do something with the button clicked

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Here I've also connected an empty slot to the signal QButtonGroup.buttonClicked, which is emitted whenever a button from the group is clicked.

To find out which button is the currently checked button, you can invoke the methods QButtonGroup.checkedButton() and QButtonGroup.checkedId(). The former will return a QButton object and the latter will return an index int, corresponding to the order in which the buttons were added to the group.

Crispin
  • 2,070
  • 1
  • 13
  • 16
  • how do you call 'QButtonGroup.checkedButton()' from inside of "on_click" method? You are passing there QPushButton, so you can ask for btn.text() but how you check group from button itself ? – tmdag Apr 14 '19 at 16:52
  • Good answer. It's worth mentioning that according to docs, [setExclusive](https://doc.qt.io/qt-5/qbuttongroup.html#exclusive-prop) property defaults to True – bfris Apr 24 '20 at 16:56
0
  1. Make the buttons checkable by setCheckable(True)
  2. Add the buttons to a QButtonGroup() and the rest is sorted automatically:

    class Example(QWidget):
       def __init__(self):
           super().__init__()
           self.setGeometry(30, 30, 400, 200)
           self.initUI()
    
       def initUI(self):
           self.button1 = QPushButton(self)
           self.button1.setGeometry(40, 40, 100, 50)
           self.button1.setText("Button 1")
           self.button1.setCheckable(True)
           self.button2 = QPushButton(self)
           self.button2.setGeometry(150, 40, 100, 50)
           self.button2.setText("Button 2")
           self.button2.setCheckable(True)
    
           self.my_button_group = QButtonGroup()
           self.my_button_group.addButton(self.button1)
           self.my_button_group.addButton(self.button2)
    
           self.show()
    
Johan
  • 863
  • 3
  • 13
  • 28
  • Actually you are correct setting buttons to get checked while clicked will be used to understand which button is currently pushed by the user. – graj499 Jun 02 '21 at 03:01