Вы используете QHBoxLayout (что означает горизонтальный макет окна). Это означает, что все добавленные вами виджеты всегда будут отображаться бок о бок по горизонтали в соответствии с порядком вставки .
Вместо этого следует использовать макет, допускающий вертикальную ориентацию.
Вы используете более одного виджета на строку, поэтому вы можете использовать QGridLayout, но, поскольку некоторые из этих виджетов имеют разные горизонтальные размеры, результат может отличаться от того, что вы нам показали. Решение состоит в использовании вложенных макетов с основным макетом сетки с наборами растяжек для первой / третьей строки и столбца и «центральным» макетом, добавленным ко второй строке / столбцу сетки. Затем, когда вам нужно более одного виджета подряд, добавьте вложенный QHBoxLayout.
class GroupBox(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setGeometry(QtCore.QRect(20, 20, 900, 700))
self.setWindowTitle("InvoiceMee - Split Documents")
layout = QtWidgets.QGridLayout(self)
groupbox = QtWidgets.QGroupBox("Files to Convert", checkable=False)
layout.addWidget(groupbox)
# the "main" layout, used to ensure that the actual layout containing
# all widgets stays in the center
groupLayout = QtWidgets.QGridLayout()
groupbox.setLayout(groupLayout)
groupLayout.setColumnStretch(0, 1)
groupLayout.setColumnStretch(2, 1)
groupLayout.setRowStretch(0, 1)
groupLayout.setRowStretch(2, 1)
# this is the actual layout used to add widgets
centerLayout = QtWidgets.QVBoxLayout()
groupLayout.addLayout(centerLayout, 1, 1)
label = QLabel()
pixmap = QPixmap('images.jpg')
label.setPixmap(pixmap)
# this won't work
# label.resize(pixmap.width(), pixmap.height())
pathBox = QtWidgets.QLineEdit(self)
pathBox.setPlaceholderText("Enter the Path Here")
# this won't work either, the layout will try to move and resize it anyway
# pathBox.setGeometry(QRect(160, 150, 201, 20))
# use minimum width instead
pathBox.setMinimumWidth(200)
selectFileBtn = QtWidgets.QPushButton("Select")
convertButton = QtWidgets.QPushButton("Convert")
good_radiobutton = QtWidgets.QRadioButton("Invoices")
naive_radiobutton = QtWidgets.QRadioButton("Credit Notes")
centerLayout.addWidget(label, alignment=QtCore.Qt.AlignCenter)
# the second row has more than one widget, use a nested horizontal layout
inputLayout = QtWidgets.QHBoxLayout()
centerLayout.addLayout(inputLayout)
inputLayout.addWidget(pathBox)
inputLayout.addWidget(selectFileBtn)
# the same for the radio buttons
radioLayout = QtWidgets.QHBoxLayout()
centerLayout.addLayout(radioLayout)
# use horizontal alignment to keep buttons closer, otherwise the layout
# will try to expand them as much as possible (depending on the other
# widgets in the centerLayout)
radioLayout.addWidget(good_radiobutton, alignment=QtCore.Qt.AlignRight)
radioLayout.addWidget(naive_radiobutton, alignment=QtCore.Qt.AlignLeft)
# use center alignment so that the button doesn't expand
centerLayout.addWidget(convertButton, alignment=QtCore.Qt.AlignCenter)
Я предлагаю вам внимательно изучить, как работает и ведет себя макет, провести несколько экспериментов, а также использовать Qt Designer для легко увидеть, как может работать вложенный макет.
Кроме того, учтите, что в некоторых случаях может потребоваться установить определенную политику размера c, чтобы виджеты не расширялись слишком сильно, и использование «контейнера» QWidget может сделать все проще. Например, вместо использования горизонтального выравнивания при добавлении переключателей вы можете использовать контейнер QWidget:
# ...
radioContainer = QtWidgets.QWidget()
centerLayout.addWidget(radioContainer, alignment=QtCore.Qt.AlignCenter)
radioContainer.setSizePolicy(QtWidgets.QSizePolicy.Maximum,
QtWidgets.QSizePolicy.Preferred)
radioLayout = QtWidgets.QHBoxLayout(radioContainer)
radioLayout.addWidget(good_radiobutton)
radioLayout.addWidget(naive_radiobutton)
# ...