1

I was using PyQt5 to create a grid layout for my username, password label and input fields and for my submit and cancel button.

I added equal row width of 1 for all my widgets, however for my cancel and submit button and I want them to be of the same cell width.

This is what I tried

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
import sys

class MainWindow(qtw.QWidget):
    
    def __init__(self, *arg, **kwargs):
        super().__init__(*arg, **kwargs)
        # custom code goes here
        username_label = qtw.QLabel('Username')
        password_label = qtw.QLabel('Password')

        username_input = qtw.QLineEdit()
        password_input = qtw.QLineEdit(echoMode = qtw.QLineEdit.Password)

        cancel_button = qtw.QPushButton('Cancel')
        submit_button = qtw.QPushButton('Login')
        
        layout = qtw.QGridLayout()
        layout.addWidget(username_label,0, 0, 1, 2) # 0,0 cell, rowspan : 1, colSpan : 2
        layout.addWidget(username_input, 0, 1, 1, 3) # 0, 1 cell
        layout.addWidget(password_label, 1, 0, 1, 2) # 1, 0 cell
        layout.addWidget(password_input, 1, 1, 1, 3) # 1, 1 cell
        layout.addWidget(cancel_button, 2, 0, 1)
        layout.addWidget(submit_button, 2, 1, 1)

        self.setLayout(layout)
        self.show()

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

However this gives me

enter image description here

Where as I expected, cancel and login to have equal width.

enter image description here

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Himanshu Poddar
  • 7,112
  • 10
  • 47
  • 93

3 Answers3

1

Modifying the lines where you add the buttons to:

layout.addWidget(cancel_button, 2, 0, 1, 1)
layout.addWidget(submit_button, 2, 1, 1, 1)

Sets them to an appropriate location:

enter image description here

My environment:

  • KDE Plasma
  • Python 3.8.2
  • PyQt5 5.15.1
jfaccioni
  • 7,099
  • 1
  • 9
  • 25
1

You need to create a separate layout for the buttons, so they can resize independently of the other widgets. Also, the problem with overlapping widgets can be fixed by using the default row/column spans. I have also added a stretchable spacer so the buttons stay at the bottom when resizing the window.

    cancel_button = qtw.QPushButton('Cancel')
    submit_button = qtw.QPushButton('Login')

    hbox = qtw.QHBoxLayout()
    hbox.addWidget(cancel_button)
    hbox.addWidget(submit_button)

    layout = qtw.QGridLayout()
    layout.addWidget(username_label,0, 0)
    layout.addWidget(username_input, 0, 1)
    layout.addWidget(password_label, 1, 0)
    layout.addWidget(password_input, 1, 1)
    layout.setRowStretch(2, 1)
    layout.addLayout(hbox, 3, 0, 1, 2)

    self.setLayout(layout)

Default:

enter image description here

Resized:

enter image description here

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
1

First of all, the column span arguments you're using are wrong: the span indicates how many cells will the widget expand starting from the indicated row or column.

If you add the label to column 0 with span 2, and the line edit to column 1 with span 3, the result will be that the label will occupy the first two column, and the line edit the second to the fourth, with the result that the line edit will be overlapped with the label. Since your layout doesn't need any spanning, you can avoid both span arguments at all.

If you then want the bottom buttons occupy half of the width, no matter the size of the widgets above, then you need to use a nested horizontal layout:

        layout = qtw.QGridLayout()
        layout.addWidget(username_label,0, 0)
        layout.addWidget(username_input, 0, 1)
        layout.addWidget(password_label, 1, 0)
        layout.addWidget(password_input, 1, 1)
        buttonLayout = qtw.QHBoxLayout()
        layout.addLayout(buttonLayout, 2, 0, 1, 2)
        buttonLayout.addWidget(cancel_button)
        buttonLayout.addWidget(submit_button)

In theory, the buttons should automatically expand, but that might depend on the current OS/style hint, so you can eventually "force" them by setting an Expanding size policy:

        cancel_button.setSizePolicy(qtw.QSizePolicy.Expanding, 
            qtw.QSizePolicy.Fixed)
        submit_button.setSizePolicy(qtw.QSizePolicy.Expanding, 
            qtw.QSizePolicy.Fixed)
musicamante
  • 41,230
  • 6
  • 33
  • 58