如何在PyQt5中对齐小部件

时间:2020-08-05 13:18:58

标签: python python-3.x pyqt5

我正在尝试将PyQt5用于我的GUI应用程序之一。我可以根据需要添加小部件,但无法正确对齐它们。我想按以下方式对齐我的小部件:

enter image description here

但是,我的代码正在像这样工作,

enter image description here

以下是我的代码,有人可以帮我吗?

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QRect
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QDesktopWidget, QLabel


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)

        hbox = QtWidgets.QHBoxLayout()
        groupbox.setLayout(hbox)
        label = QLabel()
        pixmap = QPixmap('images.jpg')
        label.setPixmap(pixmap)
        label.resize(pixmap.width(), pixmap.height())
        pathBox = QtWidgets.QLineEdit(self)
        pathBox.setPlaceholderText("Enter the Path Here")
        pathBox.setGeometry(QRect(160, 150, 201, 20))
        selectFileBtn = QtWidgets.QPushButton("Select")
        convertButton = QtWidgets.QPushButton("Convert")
        good_radiobutton = QtWidgets.QRadioButton("Invoices")
        naive_radiobutton = QtWidgets.QRadioButton("Credit Notes")
        hbox.addWidget(pathBox, alignment=QtCore.Qt.AlignCenter)
        hbox.addWidget(selectFileBtn, alignment=QtCore.Qt.AlignCenter)
        hbox.addWidget(convertButton, alignment=QtCore.Qt.AlignCenter)
        hbox.addWidget(good_radiobutton, alignment=QtCore.Qt.AlignCenter)
        hbox.addWidget(naive_radiobutton, alignment=QtCore.Qt.AlignCenter)
        hbox.addWidget(label,alignment=QtCore.Qt.AlignCenter)
        hbox.addStretch()
        self.center()


    def center(self):
        # geometry of the main window
        qr = self.frameGeometry()
        # center point of screen
        cp = QDesktopWidget().availableGeometry().center()
        # move rectangle's center point to screen's center point
        qr.moveCenter(cp)
        # top left of rectangle becomes top left of window centering it
        self.move(qr.topLeft())

2 个答案:

答案 0 :(得分:2)

使用QGridLayout代替QHBoxLayout。网格布局使您可以选择将小部件布置在诸如struture之类的网格中。这是QGridLayout的官方documentation

您可以这样更改布局:

grid = QtWidgets.QGridLayout()
groupbox.setLayout(grid)
grid.addWidget(label,0,0,1,0,QtCore.Qt.AlignCenter)
grid.addWidget(pathBox,1,0,QtCore.Qt.AlignRight)
grid.addWidget(selectFileBtn,1,1,QtCore.Qt.AlignLeft)
grid.addWidget(good_radiobutton,2,0,QtCore.Qt.AlignRight)
grid.addWidget(naive_radiobutton,2,1,QtCore.Qt.AlignLeft)
grid.addWidget(convertButton,3,0,1,0,QtCore.Qt.AlignCenter)

如果要删除小部件之间的空间,请添加垂直间隔项:

verticalSpacer = QtWidgets.QSpacerItem(40, 20,  QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
grid.addItem(verticalSpacer, 6, 0, QtCore.Qt.AlignTop)

答案 1 :(得分:1)

您使用的是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轻松了解嵌套布局的工作方式。

另外,请考虑在某些情况下可能有必要设置特定的大小策略,以避免小部件扩展过多,而使用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)
        # ...