QHBoxLayout 水平布局
水平布局,即将各个组件按先后顺序在水平方向上依次排列。
我们以一个 Dialog 窗口和四个简单 Label 作为示例:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Form(QDialog):
def __init__(self):
super(Form, self).__init__()
layout = QHBoxLayout()
layout.addWidget(QLabel("A"))
layout.addWidget(QLabel("B"))
layout.addWidget(QLabel("C"))
layout.addWidget(QLabel("D"))
self.setLayout(layout)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
效果如下:
QVBoxLayout 垂直布局
垂直布局与水平布局只是排列方向不同,用法基本相同。所有组件在垂直方向上依次排列。
同样以四个标签为例:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Form(QDialog):
def __init__(self):
super(Form, self).__init__()
layout = QHBoxLayout()
layout.addWidget(QLabel("A"))
layout.addWidget(QLabel("B"))
layout.addWidget(QLabel("C"))
layout.addWidget(QLabel("D"))
self.setLayout(layout)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
效果如下:
QGridLayout 网格布局
网格布局,以行和列来确定组件的位置。在使用layout.addWidget添加组件的时候,需要在组件后面跟上另外两个坐标参数,第一个表示行,从0开始;第二个表示列,也是从0开始。
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Form(QDialog):
def __init__(self):
super(Form, self).__init__()
layout = QGridLayout()
layout.addWidget(QLabel("A"), 0, 0)
layout.addWidget(QLabel("B"), 0, 1)
layout.addWidget(QLabel("C"), 1, 0)
layout.addWidget(QLabel("D"), 1, 1)
self.setLayout(layout)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
效果如下:
网格布局还能够指定组件所占的行数和列数,即组件能够跨行或跨列。如果要让组件占据大于一行一列的空间,可以在网格布局 addWidget
方法的参数中加上所跨行数和所跨列数,以标签C占据一行两列为例:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Form(QDialog):
def __init__(self):
super(Form, self).__init__()
layout = QGridLayout()
layout.addWidget(QLabel("A"), 0, 0)
layout.addWidget(QLabel("B"), 0, 1)
layout.addWidget(QLabel("C"), 1, 0, 1, 2)
layout.addWidget(QLabel("D"), 1, 2)
self.setLayout(layout)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
效果如下:
布局类方法
无论是QHBoxLayout、QVBoxLayout还是QGridLayout,都是属于布局对象,对于布局对象来说,很多操作都基本相同。
1. 添加子布局
在上面的例子中,我们使用布局对象的 addWidget
方法来添加组件,然后调用父对象的 setLayout
方法来采用该布局。
除了能够添加组件,我们还能够在布局中加入子布局,实现复杂的组件排列方式。添加子布局使用 addLayout
方法:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Form(QDialog):
def __init__(self):
super(Form, self).__init__()
childLayout = QGridLayout()
childLayout.addWidget(QLabel("A"), 0, 0)
childLayout.addWidget(QLabel("B"), 0, 1)
childLayout.addWidget(QLabel("C"), 1, 0)
childLayout.addWidget(QLabel("D"), 1, 1)
layout = QVBoxLayout()
layout.addWidget(QLabel("First Label"))
layout.addLayout(childLayout)
self.setLayout(layout)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
我们在外层使用了一个垂直布局,该垂直布局内先是 QLabel,然后是子布局 QGridLayout。这个子布局为网格布局,也就是上面给出的例子。这样,我们就在垂直布局中加入了网格布局,实现了垂直布局与网格布局的混合。
效果如下:
2.填充固定空白
有时候,我们希望两个组件之间留有一定的空间,此时可以通过 addSpacing
方法来添加空白。addSpacing
接收一个数值参数,用来指定空白的大小。
例如:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Form(QDialog):
def __init__(self):
super(Form, self).__init__()
childLayout = QGridLayout()
childLayout.addWidget(QLabel("A"), 0, 0)
childLayout.addWidget(QLabel("B"), 0, 1)
childLayout.addWidget(QLabel("C"), 0, 1)
childLayout.addWidget(QLabel("D"), 1, 1)
layout = QVBoxLayout()
layout.addWidget(QLabel("First Label"))
layout.addSpacing(30)
layout.addLayout(childLayout)
self.setLayout(layout)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
这个例子是在上一个例子的基础上进行修改的:在第一个组件和第二个组件之间加入了空白,使两个组件之间留有一定的空间。
效果如下:
3. 填充最大空白
在某些情况下,我们不仅希望能够用空白来占据某些空间,还希望这些空白尽可能大,但不至于覆盖余下的组件。这种情况下,我们可以使用 addStretch
方法来实现:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Form(QDialog):
def __init__(self):
super(Form, self).__init__()
buttonLayout = QHBoxLayout()
buttonLayout.addStretch()
buttonLayout.addWidget(QPushButton("Yes"))
buttonLayout.addWidget(QPushButton("No"))
layout = QVBoxLayout()
layout.addWidget(QLabel("Do you want to close this window without saving the data?"))
layout.addLayout(buttonLayout)
self.setLayout(layout)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
我们在按钮所在的水平布局里,一开始就加入了空白填充,这样一来,空白会尽可能地占据水平空间左侧,只留下最小的右侧空间给两个按钮。
效果如下:
总结
PyQt 为我们提供了上述三种最常见的布局,以及布局对应的方法。虽然单看这些布局非常简单,但是通过这些布局的组合,以及布局方法的调用,我们可以创建出非常复杂的界面。
作者:Wray Zheng
原文:http://www.codebelief.com/article/2017/04/python-gui-development-pyqt-three-kinds-of-layout/