How to list the widgets correctly within a QLayout

0

Dear,
I come before you with a problem that is currently bothering me. I'm trying to create a custom calendar in Qt, since the QCalendarWidget can not be modified or stylized, I'm doing my own.
The problem is when I try to connect the date buttons. To try to get the button I try to list them from the main container of them which is a QGirdLayout , but in doing so I always return the same widget regardless of the position of this one.

I attach the code and console image.

import calendar
import sys
import time

from PyQt4.QtCore import QSize
from PyQt4.QtGui import QApplication
from PyQt4.QtGui import QGridLayout
from PyQt4.QtGui import QPushButton
from PyQt4.QtGui import QWidget


class DayButton(QPushButton):
    def __init__(self, day):
        QPushButton.__init__(self)
        self.setText(str(day))
        self.setCheckable(True)
        self.setFixedSize(QSize(40, 40))


class Calendar(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.today = time.strftime("%x").split("/")

        self.__grid = QGridLayout()
        self.__grid.setSpacing(4)
        self.setCalendar()

        self.setLayout(self.__grid)

    def setCalendar(self):
        selectedDate = calendar.monthrange(int(self.today[2]), int(self.today[0]))

        counter, day = 0, 1
        for i in range(6):
            for j in range(7):
                if counter < selectedDate[0] or day > selectedDate[1]:
                    counter += 1
                    continue
                self.number = DayButton(str(day))
                self.number.released.connect(self.checkChecked)
                self.__grid.addWidget(self.number, i, j)
                day += 1

    def checkChecked(self):
        for item in range(self.__grid.count()):
            print self.__grid.itemAt(item)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    main = Calendar()
    main.show()

    sys.exit(app.exec_())


As you can see, the same object always returns, which is not even the type of widget I'm adding.

    
asked by Christopher Vivar Vivar 26.01.2017 в 14:51
source

2 answers

1

To list all the items in a QGridLayout you can create a generator to iterate over them using QGridLayout.itemAt(int index).widget() .

In your case you can transform the checkChecked method in the following way:

def checkChecked(self):
    items = (self.__grid.itemAt(item).widget() for item in range(self.__grid.count()))
    for item in items:
        print item

With this we get the following type output:

  

< main .DayButton object at 0x00000261B3836168 >   < main .DayButton object at 0x00000261B3836AF8 >   < main .DayButton object at 0x00000261B3836C18 >   < main .DayButton object at 0x00000261B3836438 >   < main .DayButton object at 0x00000261B3833708 >   < main .DayButton object at 0x00000261B38333A8 >   < main .DayButton object at 0x00000261B3833678 >   < main .DayButton object at 0x00000261B38338B8 >   < main .DayButton object at 0x00000261B3833E58 >   < main .DayButton object at 0x00000261B3833948 >   < main .DayButton object at 0x00000261B3833798 >   < main .DayButton object at 0x00000261B3833CA8 >   < main .DayButton object at 0x00000261B38334C8 >   < main .DayButton object at 0x00000261B38335E8 >   < main .DayButton object at 0x00000261B3833438 >   < main .DayButton object at 0x00000261B3833558 >   < main .DayButton object at 0x00000261B3833D38 >   < main .DayButton object at 0x00000261B3833828 >   < main .DayButton object at 0x00000261B3833B88 >   < main .DayButton object at 0x00000261B3833EE8 >   < main .DayButton object at 0x00000261B3833F78 >   < main .DayButton object at 0x00000261B3833DC8 >   < main .DayButton object at 0x00000261B3833AF8 >   < main .DayButton object at 0x00000261B38339D8 >   < main .DayButton object at 0x00000261B38331F8 >   < main .DayButton object at 0x00000261B3833168 >   < main .DayButton object at 0x00000261B3833288 >   < main .DayButton object at 0x00000261B3833048 >   < main .DayButton object at 0x00000261B38330D8 >   < main .DayButton object at 0x00000261B382E288 >

You can use this to modify the objects (in your case the buttons), for example, the following method changes the text of all the buttons by S :

def checkChecked(self):
    items = (self.__grid.itemAt(item).widget() for item in range(self.__grid.count()))
    for item in items:
        item.setText('S')
    
answered by 26.01.2017 / 18:20
source
1

If you want to obtain which button has been pressed it is not necessary to use the gridlayout, an elegant way is to use the function sender() that returns the object that issued the signal.

def checkChecked(self):
    obj = self.sender()
    print obj.text()

Complete code:

import calendar
import sys
import time

from PyQt4.QtCore import QSize
from PyQt4.QtGui import QApplication
from PyQt4.QtGui import QGridLayout
from PyQt4.QtGui import QPushButton
from PyQt4.QtGui import QWidget


class DayButton(QPushButton):
    def __init__(self, day):
        QPushButton.__init__(self)
        self.setText(str(day))
        self.setCheckable(True)
        self.setFixedSize(QSize(40, 40))


class Calendar(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.today = time.strftime("%x").split("/")

        self.__grid = QGridLayout()
        self.__grid.setSpacing(4)
        self.setCalendar()

        self.setLayout(self.__grid)

    def setCalendar(self):
        selectedDate = calendar.monthrange(int(self.today[2]), int(self.today[0]))

        counter, day = 0, 1
        for i in range(6):
            for j in range(7):
                if counter < selectedDate[0] or day > selectedDate[1]:
                    counter += 1
                    continue
                self.number = DayButton(str(day))
                self.number.released.connect(self.checkChecked)
                self.__grid.addWidget(self.number, i, j)
                day += 1

    def checkChecked(self):
        obj = self.sender()
        print obj.text()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = Calendar()
    w.show()
    sys.exit(app.exec_())
    
answered by 27.01.2017 в 03:48