QLayout的setAlignment(QWidget,Alignment),setAlginment(QLayout,Alignment)和setAlginment(Alignment)有什么区别



在以下代码中:

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)的情况下像下面这样调用程序时,它与"Play"按钮在顶部对齐并取消;按钮在中心垂直对齐。我还发现了bool QLayout::setAlignment(QWidget *w, Qt::Alignment对齐)的文档,尽管在Qt.

python QLayoutAlignment.py 1

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

python QLayoutAlignment.py 2

最后,我还看到了另一个例子,从居中和顶部对齐QVBoxLayout。当我像下面这样调用mainLayout.setAlignment(Qt.AlignTop)被调用的程序时,它也不能与所有按钮垂直对齐。对于这个,我找不到它的文档。那么,这个函数实际做什么(何时使用),在哪里可以找到它的文档?

python QLayoutAlignment.py 3

接受布局的.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。这是告诉您,您正在对齐的布局在当前布局中找不到。因为你在mainLayout上调用.setAlignment,你所影响的布局必须在那个布局中。

在第四个方法中,我添加了一个子布局,正如您所看到的,这(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。事实上,如果你仔细阅读文档,它说:

如果在此布局(不包括子布局)中找到w/l,则返回true;

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

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

为了澄清,考虑设置布局对齐方式与使用布局创建一个小部件,并使用指定的对齐方式添加该小部件几乎相同。考虑到这一点,它就更有意义了:您对齐的不是小部件的内容,而是小部件本身。

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

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_())

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

或者,你可以使用网格布局,并最终使用间隔符来确保小部件"对齐"。要求。

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_())

最新更新