4

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')
Nyxynyx
  • 61,411
  • 155
  • 482
  • 830
  • 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 – Mario Gil Dec 09 '16 at 11:14

5 Answers5

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.

Stefan van den Akker
  • 6,661
  • 7
  • 48
  • 63
Achayan
  • 5,720
  • 2
  • 39
  • 61
3

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.

Stefan van den Akker
  • 6,661
  • 7
  • 48
  • 63
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  
qurban
  • 3,885
  • 24
  • 36
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)
fasked
  • 3,555
  • 1
  • 19
  • 36
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.
luxiaolu
  • 111
  • 5