2

How to arrange Widgets in QGridLayout as desired? For example, In My code,

  1. I need to reduce the space between the " Country" and "State" Button

  2. Place the Widgets in top left most Corner ( Country Button in Top left Most Corner- No Margins)

  3. reduce the space between "country" and "District" Buttons

  4. Place the "bank" Button to the centre of the "Town" Button

  5. need/arrange layout as per attached image

enter image description here

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class GridLayout_Example(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Grid layout Example")
        self.setGeometry(100,100,1600,600)
        self.initUI()
        self.layout()
        self.show()

    def initUI(self):
        self.btn_country_63 = QPushButton()
        self.btn_country_63.setText("Country")
        self.btn_country_63.setObjectName("ob_btn_country_63")
        self.btn_country_63.setProperty('group', "1")
        self.btn_country_63.setFixedSize(100, 25)
        self.btn_country_63.setStyleSheet("background-color:red;color:white")
        self.btn_country_63.installEventFilter(self)
        # self.btn_country_63.clicked.connect(self.btn_country_63_select)

        self.btn_state_63 = QPushButton()
        self.btn_state_63.setText("State")
        self.btn_state_63.setObjectName("ob_btn_state_63")
        self.btn_state_63.setProperty('group', "1")
        self.btn_state_63.setFixedSize(100, 25)
        self.btn_state_63.setStyleSheet("background-color:red;color:white")
        self.btn_state_63.installEventFilter(self)
        # self.btn_state_63.clicked.connect(self.btn_state_63_select)

        self.btn_district_63 = QPushButton()
        self.btn_district_63.setText("District")
        self.btn_district_63.setObjectName("ob_btn_district_63")
        self.btn_district_63.setProperty('group', "1")
        self.btn_district_63.setFixedSize(100, 25)
        self.btn_district_63.setStyleSheet("background-color:red;color:white")
        self.btn_district_63.installEventFilter(self)
        # self.btn_district_63.clicked.connect(self.btn_district_63_select)

        self.btn_town_63 = QPushButton()
        self.btn_town_63.setText("Town")
        self.btn_town_63.setObjectName("ob_btn_town_63")
        self.btn_town_63.setProperty('group', "1")
        self.btn_town_63.installEventFilter(self)
        self.btn_town_63.setFixedSize(60, 80)
        self.btn_town_63.setStyleSheet("background-color:red;color:white")
        # self.btn_town_63.clicked.connect(self.btn_town_63_select)

        self.btn_bank_63 = QPushButton()
        self.btn_bank_63.setText("Bank")
        self.btn_bank_63.setObjectName("ob_btn_bank_63")
        self.btn_bank_63.setProperty('group', "1")
        self.btn_bank_63.installEventFilter(self)
        self.btn_bank_63.setFixedSize(100, 25)
        # self.btn_bank_63.clicked.connect(self.btn_bank_63_select)

    def layout(self):

        self.layout_main_toppannel_2_right = QGridLayout()
        self.frame_main_toppannel_2_right = QFrame()
        self.frame_main_toppannel_2_right.setProperty('color', "2")
        self.frame_main_toppannel_2_right.setFixedHeight(100)
        self.frame_main_toppannel_2_right.setStyleSheet("background-color: lightgreen")
        self.layout_main_toppannel_2_right = QGridLayout(self.frame_main_toppannel_2_right)

        self.container63 = QWidget()
        self.container63_box = QGridLayout(self.container63)
        self.container63_box.addWidget(self.btn_country_63, 0, 0, Qt.AlignTop)
        self.container63_box.addWidget(self.btn_district_63, 0, 1, Qt.AlignTop)
        self.container63_box.addWidget(self.btn_state_63, 1, 0, Qt.AlignTop)
        self.container63_box.addWidget(self.btn_town_63, 0, 3)
        self.container63_box.addWidget(self.btn_bank_63,0,4)
        self.container63_box.setColumnStretch(0,4)
        self.container63_box.setRowStretch(0,2)

      
        self.stackitem = QStackedWidget()
        self.stackitem.addWidget(self.container63)
        self.layout_main_toppannel_2_right.addWidget(self.stackitem)

        self.main_layout = QHBoxLayout()
        self.main_layout.addWidget(self.frame_main_toppannel_2_right)
        self.setLayout(self.main_layout)

def main():
    app = QApplication(sys.argv)
    mainwindow = GridLayout_Example()
    mainwindow.show()
    sys.exit(app.exec_())
if __name__ == "__main__":
    main()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Kumar
  • 592
  • 6
  • 18
  • 1
    Recommendation: for your next post, eliminate the code that does not intervene in the problem, such as the eventfilter, the setProperty, etc., since they are only noise that does not allow us to understand the cause of the problem. Also try to place images that help to understand the problem without distracting us, your initial image had a lot of unnecessary empty space. – eyllanesc May 17 '21 at 04:10
  • Ok. Noted. @eyllanesc – Kumar May 17 '21 at 04:13
  • @Kumar I also suggest you to do much more experimenting with Designer (looking at your code, you clearly have been using it), possibly with different types of widgets, starting with the basic "Widget" (which is a QWidget, it's in the "Containers" section). Try different combinations and layouts (including nested layouts), and variations of their properties (minimum/maximum sizes, size policies, etc). Test various widgets, observe their default behavior and changes when resizing and modifying their properties, so that you can better learn how to deal with all of this. – musicamante May 17 '21 at 04:37
  • Thankyou @musicamante. Follow your guideness – Kumar May 17 '21 at 04:44

1 Answers1

7

In a previous post I explained in detail the operation of the QGridLayout so in this post I will only detail the most outstanding.

  • To remove the space between the items you must use setSpacing(0) (you can also use setHorizontalSpacing(0) and setVerticalSpacing(0)).

  • To make the elements be pushed to the left you can set a stretch to the imaginary fifth column.

  • I have also modified the height of "Town" since it does not match the sum height of the 3 elements, forcing spaces to appear.

  • I also calculated the height of the green container after setting the items to match the space needed and there are no spaces.

  • Finally note that some margins cannot be changed by code since they are implemented by the native QStyles of the OS, to avoid that I impose that the style fusion be used.

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class GridLayout_Example(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.build_widgets()
        self.build_layout()

        self.resize(640, 480)

    def build_widgets(self):
        self.btn_country_63 = QPushButton(
            text="Country", styleSheet="background-color:red;color:white"
        )
        self.btn_country_63.setFixedSize(100, 25)

        self.btn_state_63 = QPushButton(
            text="State", styleSheet="background-color:red;color:white"
        )
        self.btn_state_63.setFixedSize(100, 25)

        self.btn_district_63 = QPushButton(
            text="District", styleSheet="background-color:red;color:white"
        )
        self.btn_district_63.setFixedSize(100, 25)

        self.btn_town_63 = QPushButton(
            text="Town", styleSheet="background-color:red;color:white"
        )
        self.btn_town_63.setFixedSize(60, 75)

        self.btn_bank_63 = QPushButton(
            text="Bank", styleSheet="background-color:red;color:white"
        )
        self.btn_bank_63.setFixedSize(100, 25)

        self.btn_zip_63 = QPushButton(
            text="Zip Code", styleSheet="background-color:red;color:white"
        )
        self.btn_zip_63.setFixedSize(100, 25)

    def build_layout(self):
        self.container = QFrame()
        self.container.setStyleSheet("background-color: lightgreen")

        grid_layout = QGridLayout(self.container)
        grid_layout.addWidget(self.btn_country_63, 0, 0, 1, 1)
        grid_layout.addWidget(self.btn_state_63, 1, 0, 1, 1)
        grid_layout.addWidget(self.btn_district_63, 0, 1, 1, 1)
        grid_layout.addWidget(self.btn_town_63, 0, 2, 3, 1)
        grid_layout.addWidget(self.btn_bank_63, 1, 3, 1, 1)
        grid_layout.addWidget(self.btn_zip_63, 2, 4, 1, 1)
        grid_layout.setColumnStretch(5, 1)
        grid_layout.setSpacing(0)
        grid_layout.setContentsMargins(0, 0, 0, 0)

        lay = QVBoxLayout(self)
        lay.addWidget(self.container)
        self.container.setFixedHeight(self.container.sizeHint().height())


def main():
    app = QApplication(sys.argv)
    print("default-style: ", app.style().metaObject().className())
    app.setStyle("fusion")
    mainwindow = GridLayout_Example()
    mainwindow.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Your answers are always detailed, thorough, and helpful for other readers as well, thanks for that. I read somewhere in the internet that `QGridLayout` is generally avoided, and strictly used for table like appearance only, and even in such scenarios, combination of `Vertical` and `Horizontal` layouts are preferred most of the time, I also believe so, what's your opinion on that? Since this question is also about `QGridLayout`, I just wanted to know your opinion in that regard. – ThePyGuy Jun 05 '21 at 04:14
  • 1
    @Don'tAccept What you indicate to me is an opinion without any basis. In the post that you indicate, does it indicate an argument of efficiency, of design or of something that intervenes in the development of the software? For me in many cases I have used the layouts interchangeably, that is, for me the same requirement can often be fulfilled using different layouts. So my opinion is very practical: If QGridLayout solves your problem then keep using it. Another thing is that you will argue with me some practical problem. – eyllanesc Jun 05 '21 at 04:22
  • [@eyllanesc](https://stackoverflow.com/users/6622587/eyllanesc) Thanks for your response, I got the point. – ThePyGuy Jun 05 '21 at 04:24