PyQt4中的布局管理
单击此处查看原文。
GUI编程中一个重要的方面就是布局管理。布局管理是如何将小部件放置在主窗口上的方式。布局管理有两种基本的方式:绝对定位和布局类。
1 绝对定位(Absolute positioning)
程序员为每个部件以像素为单位制定其位置和大小。当使用绝对定位时,需要了解以下的限制:
- 当窗口大小改变时,部件的大小和位置不会发生变化;
- 在不同平台上,应用程序可能显示效果不一致;
- 在应用程序中改变字体可能会破坏布局;
- 当要改变布局时,需要完全重做所有的布局,这是相当繁琐以及费时的。
下面的代码展示了绝对布局。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
lbl1 = QtGui.QLabel('ZetCode', self)
lbl1.move(15, 10)
lbl2 = QtGui.QLabel('tutorials', self)
lbl2.move(35, 40)
lbl3 = QtGui.QLabel('for programmers', self)
lbl3.move(55, 70)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Absolute')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
2 框布局(Box layout)
由布局类提供的布局管理更加的灵活和实用。它是将小部件放置在主窗口上的首先方法。QtGui.QHBoxLayout和QtGui.QVBoxLayout是基本的布局类用于横向或纵向排列小部件。
假设,我们需要将两个按钮放置在窗口的右下角。我们可以创建一个水平和垂直的布局,并保留足够的空间,同时添加伸缩因子。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
# 创建两个按钮。
okButton = QtGui.QPushButton('OK')
cancelButton = QtGui.QPushButton('Cancel')
# 创建水平框布局对象,添加伸缩因子和两个按钮。
# 这个伸缩因子在窗口改变时会在其前面添加空白。
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
# 创建一个垂直框布局对象,并将水平框布局对象
# 添加到垂直框布局对象中。
vbox = QtGui.QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
# 设置主窗口的布局。
self.setLayout(vbox)
self.setGeometry(300, 300, 300, 150)
self.setWindowTitle('Box Layout')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
上面的代码中在主窗口的右下角创建了两个按钮。当改变应用程序窗口大小时,它们仍然保持在窗口的右下角。我们同时使用了QtGui.HBoxLayout和QtGui.VBoxLayout。
3 网格布局(QGridLayout)
最通用的布局类应属网格布局了。这种布局方式将空间分为行列阵。使用QtGui.QGridLayout类可以创建网格布局对象。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
# 创建网络布局对象,并加入到应用程序主窗口中。
grid = QtGui.QGridLayout()
self.setLayout(grid)
names = ['Cls', 'Bck', '', 'Close',
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', '=', '+']
positions = [(i,j) for i in range(5) for j in range(4)]
for position, name in zip(positions, names):
if name == '':
continue
# 创建按钮并加入到网格中。
button = QtGui.QPushButton(name)
grid.addWidget(button, *position)
self.move(300, 150)
self.setWindowTitle('Calculator')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
在网格布局中,一个部件可跨越多个列或行。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
title = QtGui.QLabel('Title')
author = QtGui.QLabel('Author')
review = QtGui.QLabel('Review')
titleEdit = QtGui.QLineEdit()
authorEdit = QtGui.QLineEdit()
reviewEdit = QtGui.QTextEdit()
# 创建网格布局对象,并设置部件之间的间距。
grid = QtGui.QGridLayout()
grid.setSpacing(10)
grid.addWidget(title, 1, 0)
grid.addWidget(titleEdit, 1, 1)
grid.addWidget(author, 2, 0)
grid.addWidget(authorEdit, 2, 1)
# 添加部件到网格中,并指定跨越的行。
grid.addWidget(review, 3, 0)
grid.addWidget(reviewEdit, 3, 1, 5, 1)
self.setLayout(grid)
self.setGeometry(300, 300, 350, 300)
self.setWindowTitle('Review')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我们创建了三个标签,两个行输入框,一个文件输入框,采用网格布局。