5

I'm new to Python and PyQt and this is my first application. Currently when a button is clicked, toggleLED() checks self.LedOn to decide whether to turn an LED on.

class Screen(QWidget):

    def initUI(self):
        self.LedOn = 0

        btn = QPushButton('Off', self)
        btn.setCheckable(True)
        btn.clicked.connect(self.toggleLED)


    def toggleLED(self, pressed):

        source = self.sender()

        if self.LedOn:
            source.setText('Off')
            source.LedOn = 0
            self.serial.write('L')
        else:           
            source.setText('On')
            source.LedOn = 1
            self.serial.write('H')

Problem: Now if we want to control multiple LEDs and remember their individual toggle state, what is the best practice?

I also cant seem to pass an additional value to toggleLED() with btn.clicked.connect(self.toggleLED(btnNumber))

class Screen(QWidget):

    def initUI(self):

        btn1 = QPushButton('Off', self)
        btn1.setCheckable(True)
        btn1.LedOn= 0
        btn1.clicked.connect(selftoggleLED(1))

        btn2 = QPushButton('Off', self)
        btn2.setCheckable(True)
        btn2.LedOn= 0
        btn2.clicked.connect(selftoggleLED(2))


    def toggleLED(self, pressed, value):

        source = self.sender()

        if self.LedOn:
            source.setText('Off')
            self.serial.write(value)
            self.serial.write('L')
        else:           
            source.setText('On')
            self.serial.write(value)
            self.serial.write('H')
1
  • I believe you need to subclass QPushButton and somehow reimplement clicked or pressed signal emmiters to return your desired value, but I can't find how to do this in pyqt's documentation Commented Dec 9, 2016 at 11:14

5 Answers 5

7

You can use partial for that:

from functools import partial

btn1.clicked.connect(partial(self.toggleLED, 1))

This allows you to pass multiple arguments to a function.

Sign up to request clarification or add additional context in comments.

Comments

4

To pass multiple arguments to a function, you can use either functools.partial() or a lambda:

btn2.clicked.connect(lambda: selftoggleLED(2))

Read the discussion of both methods.

Comments

1

Here is the solution that I always use for this job.

class Screen(QWidget):

    def initUI(self):

        btn1 = QPushButton('Off', self)
        btn1.setCheckable(True)
        btn1.LedOn= 0
        btn1.clicked.connect(selftoggleLED(1))

        btn2 = QPushButton('Off', self)
        btn2.setCheckable(True)
        btn2.LedOn= 0

        # I am adding these lines-----------------------

        # put all the btns in a list
        btns = [btn1, btn2]
        # connect each btn with the function and pass the same btn
        map(lambda btn: btn.clicked.connect(lambda pressed: self.toggleLED(pressed, btn)), btns)


    def toggleLED(self, pressed, clikedBtn):

        if pressed:
            clickedBtn.setText("On")
            # set other variables you need
        else: 
            clickedBtn.setText("Off")
            # set other variables  

Comments

0
class Screen(QWidget):

    def initUI(self):

        btn1 = QPushButton('Off', self)
        btn1.setCheckable(True)
        btn1.value = 1
        btn1.clicked.connect(selftoggleLED)

        btn2 = QPushButton('Off', self)
        btn2.setCheckable(True)
        btn2.value = 2
        btn2.clicked.connect(selftoggleLED)


    def toggleLED(self, pressed):

        source = self.sender()

        if pressed:
            source.setText('Off')
            self.serial.write(source.value)
            self.serial.write('L')
        else:           
            source.setText('On')
            self.serial.write(source.value)
            self.serial.write('H')
  1. The checkable QPushButton will store the state, so you don't need btn.LedOn.
  2. Use btn.value to store the btn number, so you don't need to send the extra arg.

Comments

0

QPushButton does already have checked boolean property, so you don't need to create another one. There are two signals which button emits:

  1. clicked when it's pressed
  2. toggled when its state is changed

Both of them transfer parameter which indicates a button's state. But I think, the second is more appropriate because of its name.

So the toggleLED slot should looks like this:

def toggleLED(self, checked):
    source = self.sender()
    if checked:
        source.setText('Off')
        self.serial.write('L')
    else:           
        source.setText('On')
        self.serial.write('H')

Notice that only checkable buttons emit toggled signal, but you already set this property in your code:

def initUI(self):
    btn1 = QPushButton('Off', self)
    btn1.setCheckable(True)
    btn1.toggled.connect(self.toggleLED)

    btn2 = QPushButton('Off', self)
    btn2.setCheckable(True)
    btn2.toggled.connect(self.toggleLED)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.