Karthik Suresh
Karthik Suresh

Reputation: 25

PyQt : How to use the QCheckBox.isChecked() method

The Below code is written to select the seats in an auditorium screen.. As I select the CheckBox i need the result to be displayed(Price of the Ticket) and also when I try to uncheck the CheckBox the result should be subtracted and displayed, Instead of this It's just keeps adding the result by 180 ...

import sys
from PyQt4 import QtGui, QtCore, QtSql

class SeatSel(QtGui.QWidget):
    def __init__(self, parent=None):
        super(SeatSel, self).__init__(parent)
        self.a = {}
        self.l = {}
        self.l1 = QtGui.QLabel("\t\t     Screen", self)
        self.l1.setStyleSheet("color : black")
        self.l1.move(210,600)
        self.l1.setAutoFillBackground(True)
        self.l1.setMinimumWidth(700)
        self.l3 = QtGui.QLabel("00              " ,self)
        self.l3.setStyleSheet("color : white")
        self.l3.move(1000, 500)
        self.l3.setMaximumWidth(300)
        self.display = QtGui.QLabel(self)
        self.display.setStyleSheet("color : white")
        self.display.move(800,800)

        for i in range(14):
            self.l[(i)] = QtGui.QLabel("%s" % chr(65+i), self)
            self.l[(i)].setStyleSheet("color : white")
            self.l[(i)].move(110, 103 + i * 32)

        for i in range(26):
            for j in range(14):
                self.a[(i,j)] = QtGui.QCheckBox(self)
                self.a[(i,j)].setMaximumSize(40,40)
                self.a[(i,j)].setCheckable(True)
                self.a[(i,j)].move(160+ (i-1) * 31,100 + j *32)

    def seat(self, m_name, x, y):
        self.l2 = QtGui.QLabel(m_name, self)
        self.l2.move(x,y)
        self.l2.setStyleSheet("color : white")


class DeadPool(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(QtGui.QMainWindow, self).__init__(parent)
        self.amount = 0
        self.count = 0
        self.setGeometry(50, 50, 1920, 1080)
        self.showMaximized()
        self.seat_sel("Conjuring", 640,40)

    def full_screen(self):
         if self.count == 0:
             self.count=1
             self.showFullScreen()
         else :
             self.count = 0
             self.showNormal()

    def exit(self):
        sys.exit()


    def seat_sel(self, m_name, x, y):
        self.seat = SeatSel(self)
        self.setWindowTitle("Select Seats")
        self.setCentralWidget(self.seat)
        self.seat.seat(m_name, x, y)
        for i in range(26):
            for j in range(14):
                self.seat.a[(i,j)].stateChanged.connect(lambda :
                                       self.seat_buttons(i, j))
        self.show()

    def seat_buttons(self, i, j):
        self.btn_toggle(self.seat.a[(i,j)])

    def btn_toggle(self, button):
        if button.isChecked():
            self.amount -= 180
            self.seat.l3.setNum(self.amount)
        if not button.isChecked():
            self.amount += 180
            self.seat.l3.setNum(self.amount)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    w = DeadPool()
    sys.exit(app.exec_())

Upvotes: 1

Views: 1642

Answers (1)

ekhumoro
ekhumoro

Reputation: 120768

There is a problem in how you connect the stateChanged signal to the lambda slot. When you connect signals in a loop, the variables are not cached, so every lambda will end up with the same values (i.e. whatever the final values of the variables are when the loop exits). There are several ways to fix this. One way is to explicitly cache the values using default arguments:

    for i in range(26):
        for j in range(14):
            self.seat.a[(i,j)].stateChanged.connect(
                lambda state, i=i, j=j: self.seat_buttons(i, j))

Another way is to use functools.partial:

from functools import partial
...

    for i in range(26):
        for j in range(14):
            self.seat.a[(i,j)].stateChanged.connect(
                partial(self.seat_buttons, i, j))

But even simpler in your case, would be to use sender(), which returns whatever object sent the signal:

    for i in range(26):
        for j in range(14):
            self.seat.a[(i,j)].stateChanged.connect(self.btn_toggle)
...    

def btn_toggle(self, state):
    button = self.sender()
    if button.isChecked():
        self.amount += 180
        self.seat.l3.setNum(self.amount)
    else:
        self.amount -= 180
        self.seat.l3.setNum(self.amount)

(PS: note that I've swapped the +/- because I think they are the wrong way around in your example code)

Upvotes: 1

Related Questions