Qt getting column position of clicked item

pyqt, pyqt4, qt

Solution

You can simply ask the QGridLayout where the items are. Here is an example:

class Widget(QtGui.QWidget):

    def __init__(self):
        super(Widget, self).__init__()
        self.resize(600,600)

        self.layout = QtGui.QGridLayout(self)
        for row in xrange(3):
            for col in xrange(3):
                button = QtGui.QPushButton("Button %d-%d" % (row,col))
                button.clicked.connect(self.buttonClicked)
                self.layout.addWidget(button, row, col)

    def buttonClicked(self):
        button = self.sender()
        idx = self.layout.indexOf(button)
        location = self.layout.getItemPosition(idx)
        print "Button", button, "at row/col", location[:2]

All you need to know is which widget was clicked. Then you can look up the layout index with `layout.indexOf(widget)`. With the index, you can lookup the actual `(row, col, rowspan, colspan)` using `layout.getItemPosition(index)`

No need to loop over the entire contents of the list. Also, with this approach you get the current location, as opposed to any stored column positions when the item was created. Item's can be moved around inside of a layout at any time after they have been added.

If you find the `self.sender()` approach "unpythonic" because you have to ask it who the calling widget was, you can also use the approach of packaging up each callback with the actual button widget ahead of time:

from functools import partial 

class Widget(QtGui.QWidget):

    def __init__(self):
        ...
            for col in xrange(3):
                button = QtGui.QPushButton("Button %d-%d" % (row,col))
                cbk = partial(self.buttonClicked, button)
                button.clicked.connect(cbk)
        ...
    def buttonClicked(self, button):
        idx = self.layout.indexOf(button)

Problem

I have three widgets contained in a grid layout. When I click them I'd like to get their column position but I cannot find any property of the widget itself and cannot seem to get hold of the container by accessing `widget.parentWidget()` I could use some indirect way such as itemAt but I'd rather find a less convoluted way of doing it.

Original source