Search code examples
pythonpyqtpyqt5qgridlayout

Is there a way to know the X and Y coordinates of an element in a QGridLayout?


I have a QGridLayout where I'm adding different elements and I need to know the elements and I need to know the coordinates of of a specific element. Is there a way of doing this? I read the documentation and tried using the pos() and geometry() attributes but I couldn't get what I wanted. For example, given the following code:

import sys
from PyQt5.QtWidgets import (QWidget, QGridLayout,QPushButton, QApplication)

class basicWindow(QWidget):
    def __init__(self):
        super().__init__()
        grid_layout = QGridLayout()
        self.setLayout(grid_layout)

        for x in range(3):
            for y in range(3):
                button = QPushButton(str(str(3*x+y)))
                grid_layout.addWidget(button, x, y)

        self.setWindowTitle('Basic Grid Layout')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    windowExample = basicWindow()
    windowExample.show()
    sys.exit(app.exec_())

Is there a way of knowing the coordinates of each button?


Solution

  • The geometry is updated only when the widget is displayed, so you are probably printing the coordinates before displaying it. In the following example, if you press any button, it will print the coordinates with respect to the window.

    import sys
    from PyQt5.QtCore import pyqtSlot
    from PyQt5.QtWidgets import QWidget, QGridLayout, QPushButton, QApplication
    
    
    class BasicWindow(QWidget):
        def __init__(self):
            super().__init__()
            grid_layout = QGridLayout(self)
    
            for x in range(3):
                for y in range(3):
                    button = QPushButton(str(3 * x + y))
                    button.clicked.connect(self.on_clicked)
                    grid_layout.addWidget(button, x, y)
    
            self.setWindowTitle("Basic Grid Layout")
    
        @pyqtSlot()
        def on_clicked(self):
            button = self.sender()
            print(button.text(), ":", button.pos(), button.geometry())
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        windowExample = BasicWindow()
        windowExample.show()
        sys.exit(app.exec_())
    

    Output:

    0 : PyQt5.QtCore.QPoint(10, 10) PyQt5.QtCore.QRect(10, 10, 84, 34)
    4 : PyQt5.QtCore.QPoint(100, 50) PyQt5.QtCore.QRect(100, 50, 84, 34)
    8 : PyQt5.QtCore.QPoint(190, 90) PyQt5.QtCore.QRect(190, 90, 84, 34)
    

    Update:

    If you want to get the position of the widget given the row and column, the first thing is to get the QLayoutItem, and from that QLayoutItem you must get the widget. In the following example, the position of a button is printed a moment after the window is displayed:

    import sys
    from PyQt5.QtCore import QTimer
    from PyQt5.QtWidgets import QWidget, QGridLayout, QPushButton, QApplication
    
    
    class basicWindow(QWidget):
        def __init__(self):
            super().__init__()
            grid_layout = QGridLayout(self)
    
            for x in range(3):
                for y in range(3):
                    button = QPushButton(str(3 * x + y))
                    grid_layout.addWidget(button, x, y)
    
            self.setWindowTitle("Basic Grid Layout")
    
            QTimer.singleShot(0, lambda: self.print_coordinates(1, 1))
    
        def print_coordinates(self, x, y):
            grid_layout = self.layout()
            it = grid_layout.itemAtPosition(x, y)
            w = it.widget()
            print(w.pos())
    
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        windowExample = basicWindow()
        windowExample.show()
        sys.exit(app.exec_())