QLayout的设置对齐(QWidget,对齐)、设置对齐(QLayout,对齐)和设置对齐(对齐)之间有什么区别?(PyQt5)

2024-09-30 22:14:12 发布

您现在位置:Python中文网/ 问答频道 /正文

在以下代码中:

import sys

from PyQt5           import QtWidgets
from PyQt5.QtCore    import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QTableWidget, QPushButton

class Window(QtWidgets.QMainWindow):
    def __init__(self, method):
        super(Window, self).__init__()

        mainWidget = QWidget()
        mainLayout = QHBoxLayout(mainWidget)

        table = QTableWidget(10, 3)
        button1 = QPushButton("Play")
        button2 = QPushButton("Cancel")

        mainLayout.addWidget(table)
        mainLayout.addWidget(button1)
        mainLayout.addWidget(button2)

        if   (method == 1):
            rtnValue = mainLayout.setAlignment(button1, Qt.AlignTop)
            print("Method 1:", rtnValue)
        elif (method == 2):
            rtnValue = mainLayout.setAlignment(mainLayout, Qt.AlignTop)
            print("Method 2:", rtnValue)
        else:
            rtnValue = mainLayout.setAlignment(Qt.AlignTop)
            print("Method X:", rtnValue)

        self.setCentralWidget(mainWidget)
        self.show()

if __name__ == "__main__":
    print("python QLayoutAlignment.py[ <MethodToUse=1>")
    app = QApplication(sys.argv)
    method = 1 if (len(sys.argv) < 2) else int(sys.argv[1])
    GUI = Window(method)
    sys.exit(app.exec_())

当我在调用mainLayout.setAlignment(button1, Qt.AlignTop)的情况下调用下面这样的程序时,它会像预期的那样工作,“播放”按钮在顶部对齐,“取消”按钮在垂直中心对齐。我还在Qt中找到了bool QLayout::setAlignment(QWidget *w, Qt::Alignment alignment)的文档

python QLayoutAlignment.py 1

然而,当我像下面那样调用程序,调用mainLayout.setAlignment(mainLayout, Qt.AlignTop)时,它似乎不起作用。所有按钮都垂直居中对齐。我将bool QLayout::setAlignment(QLayout *l, Qt::Alignment alignment)的Qt文档解释为“它将所有添加的布局小部件与集合对齐对齐”。那么这个函数实际上做什么(何时使用)

python QLayoutAlignment.py 2

最后,我还看到了来自Center and top align a QVBoxLayout的另一个例子。当我在调用mainLayout.setAlignment(Qt.AlignTop)的情况下调用下面这样的程序时,它也不会在所有按钮垂直居中对齐的情况下工作。对于这一个,我找不到它的文档。那么这个函数实际上做什么(何时使用)以及在哪里可以找到它的文档

python QLayoutAlignment.py 3

Tags: 文档pyimportselfsysqt按钮method
2条回答

接受布局的.setAlignment方法用于对齐子布局,即使用.addLayout添加到父布局的子布局

下面是一个基于您的代码的小演示

import sys

from PyQt5           import QtWidgets
from PyQt5.QtCore    import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QTableWidget, QPushButton

class Window(QtWidgets.QMainWindow):
    def __init__(self, method=0):
        super(Window, self).__init__()

        mainWidget = QWidget()
        self.mainLayout = QHBoxLayout(mainWidget)

        table = QTableWidget(10, 3)
        self.button1 = QPushButton("Play")
        self.button2 = QPushButton("Cancel")

        self.subLayout = QHBoxLayout()
        buttona1 = QPushButton("1")
        buttona1.clicked.connect(self.clicked1)
        buttona2 = QPushButton("2")
        buttona2.clicked.connect(self.clicked2)
        buttona3 = QPushButton("3")
        buttona3.clicked.connect(self.clicked3)
        buttona4 = QPushButton("4")
        buttona4.clicked.connect(self.clicked4)
        self.subLayout.addWidget(buttona1)
        self.subLayout.addWidget(buttona2)
        self.subLayout.addWidget(buttona3)
        self.subLayout.addWidget(buttona4)

        self.mainLayout.addWidget(table)
        self.mainLayout.addWidget(self.button1)
        self.mainLayout.addWidget(self.button2)
        self.mainLayout.addLayout(self.subLayout)

        self.setCentralWidget(mainWidget)
        self.show()

    def clicked1(self):
        rtnValue = self.mainLayout.setAlignment(self.button1, Qt.AlignTop)
        print("Method 1:", rtnValue)

    def clicked2(self):
        rtnValue = self.mainLayout.setAlignment(self.mainLayout, Qt.AlignTop)
        print("Method 2:", rtnValue)

    def clicked3(self):
        rtnValue = self.mainLayout.setAlignment(Qt.AlignTop)
        print("Method 3:", rtnValue)

    def clicked4(self):
        rtnValue = self.mainLayout.setAlignment(self.subLayout, Qt.AlignTop)
        print("Method 4:", rtnValue)


if __name__ == "__main__":
    print("python QLayoutAlignment.py[ <MethodToUse=1>")
    app = QApplication(sys.argv)
    method = 1 if (len(sys.argv) < 2) else int(sys.argv[1])
    GUI = Window(method)
    sys.exit(app.exec_())

您会注意到,如果触发此self.mainLayout.setAlignment(self.mainLayout, Qt.AlignTop),返回值为False。此is telling you表明在当前布局中找不到正在对齐的布局。由于您正在mainLayout上调用.setAlignment,因此您影响的布局必须在该布局中

在第4个方法中,我添加了一个子布局,正如您所看到的(rtnValue = self.mainLayout.setAlignment(self.subLayout, Qt.AlignTop))按预期工作并返回True

首先,了解Qt布局系统通过使用布局项(请参见QLayoutItem)工作是很重要的,它们是用作对象的虚拟容器的抽象项:小部件、间隔符和布局(使用嵌套布局时)。实际上,每个QLayout都是QLayoutItem的一个子类

使用setAlignment表示设置指定布局项的对齐方式:

  • layout.setAlignment(item, alignment)设置item的对齐方式,直接包含在layout
  • layout.setAlignment(alignment)设置与其父布局相关的layout的对齐方式;注意,这并不意味着layout内的项目将使用指定的对齐方式

您的第二个案例mainLayout.setAlignment(mainLayout, Qt.AlignTop)不起作用并返回False,因为mainLayout显然不“包含”在mainLayout中。事实上,如果您仔细阅读文档,它会说:

returns true if w/l is found in this layout (not including child layouts);

在第三种情况下,您看不到任何结果,因为mainLayout是小部件的顶部布局,并且由于没有父布局,对齐似乎被忽略。如上所述,使用layout.setAlignment(alignment)不会设置子项的对齐方式,而只设置layout的布局项的对齐方式。如果将该mainLayout添加到另一个布局中,您将看到布局的对齐方式受到尊重

设置布局对齐很少被使用,这也是因为它通常是违反直觉的:人们可能会认为设置布局对齐将对齐其内容,但事实并非如此

阐明,考虑设置布局对齐与创建具有 > EEM>布局的小部件几乎相同,并添加具有指定对齐方式的小部件。考虑到这一点,它更有意义:您不是在对齐小部件的内容,而是在对齐小部件本身

考虑下面的例子:除了左边的表(用于比较),我还通过指定它的对齐方式在左边添加一个布局,然后通过指定主布局的窗口小部件的对齐方式,在右边添加一个小部件。正如你所看到的,它们看起来完全一样

from PyQt5 import QtCore, QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

test = QtWidgets.QWidget()
mainLayout = QtWidgets.QHBoxLayout(test)
# a very tall table to show the difference in alignment
mainLayout.addWidget(QtWidgets.QTableView(minimumHeight=300))

leftLayout = QtWidgets.QHBoxLayout()
# setting the alignment of leftLayout relative to mainLayout
leftLayout.setAlignment(QtCore.Qt.AlignTop)
leftLayout.addWidget(QtWidgets.QTableView(maximumHeight=100))
leftLayout.addWidget(QtWidgets.QPushButton())
mainLayout.addLayout(leftLayout)

rightWidget = QtWidgets.QWidget()
# adding the widget to mainLayout by aligning it on top as with leftLayout
mainLayout.addWidget(rightWidget, alignment=QtCore.Qt.AlignTop)
rightLayout = QtWidgets.QHBoxLayout(rightWidget)
rightLayout.addWidget(QtWidgets.QTableView(maximumHeight=100))
rightLayout.addWidget(QtWidgets.QPushButton())

test.show()
sys.exit(app.exec_())

最后,如果要对齐小部件,可以指定每个小部件的对齐方式,或者添加嵌套布局。
当许多小部件要以相同的对齐方式添加时,嵌套布局通常是最好的解决方案:在您的情况下,向主布局添加垂直布局,然后为按钮向垂直方向添加水平布局,并向垂直方向添加拉伸以“推”顶部的水平布局

或者,您可以使用网格布局并最终使用间隔符来确保小部件根据需要“对齐”

from PyQt5 import QtCore, QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)

test = QtWidgets.QWidget()
mainLayout = QtWidgets.QHBoxLayout(test)

class Button(QtWidgets.QPushButton):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setSizePolicy(
            QtWidgets.QSizePolicy.Preferred, 
            QtWidgets.QSizePolicy.Preferred
        )

noAlignGroup = QtWidgets.QGroupBox('no alignment')
mainLayout.addWidget(noAlignGroup)
noAlignLayout = QtWidgets.QHBoxLayout(noAlignGroup)
noAlignLayout.addWidget(QtWidgets.QTableView())
noAlignLayout.addWidget(Button())
noAlignLayout.addWidget(Button())

widgetAlignGroup = QtWidgets.QGroupBox('addWidget(widget, alignment)')
mainLayout.addWidget(widgetAlignGroup)
widgetAlignLayout = QtWidgets.QHBoxLayout(widgetAlignGroup)
widgetAlignLayout.addWidget(QtWidgets.QTableView())
widgetAlignLayout.addWidget(Button(), alignment=QtCore.Qt.AlignTop)
widgetAlignLayout.addWidget(Button(), alignment=QtCore.Qt.AlignTop)

layoutAlignGroup = QtWidgets.QGroupBox('nestedLayout.setAlignment()')
mainLayout.addWidget(layoutAlignGroup)
layoutAlignLayout = QtWidgets.QHBoxLayout(layoutAlignGroup)
layoutAlignLayout.addWidget(QtWidgets.QTableView())
buttonLayout = QtWidgets.QHBoxLayout()
layoutAlignLayout.addLayout(buttonLayout)
buttonLayout.setAlignment(QtCore.Qt.AlignTop)
buttonLayout.addWidget(Button())
buttonLayout.addWidget(Button())

stretchGroup = QtWidgets.QGroupBox('nestedLayout + stretch')
mainLayout.addWidget(stretchGroup)
stretchLayout = QtWidgets.QHBoxLayout(stretchGroup)
stretchLayout.addWidget(QtWidgets.QTableView())
rightLayout = QtWidgets.QVBoxLayout()
stretchLayout.addLayout(rightLayout)
buttonLayout = QtWidgets.QHBoxLayout()
rightLayout.addLayout(buttonLayout)
buttonLayout.addWidget(Button())
buttonLayout.addWidget(Button())
rightLayout.addStretch()

gridAlignGroup = QtWidgets.QGroupBox('grid + spacer')
mainLayout.addWidget(gridAlignGroup)
gridLayout = QtWidgets.QGridLayout(gridAlignGroup)
gridLayout.addWidget(QtWidgets.QTableView(), 0, 0, 2, 1)
gridLayout.addWidget(Button(), 0, 1)
gridLayout.addWidget(Button(), 0, 2)
spacer = QtWidgets.QSpacerItem(1, 50, vPolicy=QtWidgets.QSizePolicy.Expanding)
gridLayout.addItem(spacer, 1, 1)

test.show()
sys.exit(app.exec_())

相关问题 更多 >