(本系列中所有代码在windows7 64位[]/Python 3.4.3 32bit/PyQt GPL v5.5 for Python v3.4 (x32)/eric6-6.0.8下测试通过.)
原本地址:http://zetcode.com/gui/pyqt5/
================================================================================
GUI程序的重要一个方面就是布局管理.布局管理是我们如何将部件放到程序窗口内.这有两种方法.即绝对定位和布局类.
绝对定位
程序员定位每个部件的位置和大小到像素级.当你使用绝对定位时,我们需要明白以下的限制:
如果我们改变一个窗口的大小时,一个部件的大小和定位不能更改.
程序可能在不同平台上看起来不一样.
在我们的程序内改变字体时可能会破坏布局
如果我们决定修改布局,我们必须全部重做我们的布局,那可是繁琐又费时的.
下面的例子是用绝对定位布局部件.
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
lbl1 = QLabel('Zetcode', self)
lbl1.move(15, 10)
lbl2 = QLabel('tutorials', self)
lbl2.move(35, 40)
lbl3 = QLabel('for programmers', self)
lbl3.move(55, 70)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Absolute')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
我们用mover()方法来定位我们的部件.在这个例子中部件是标签.我们定位他们的时候是用的坐标轴的x和y.最开始的坐标系统是在左上角.x是从左到右的,y是从上到下的.
lbl1 = QLabel('Zetcode', self)标签部件定位在x=15,y=10的位置.
lbl1.move(15, 10)
图片:绝对定位
框布局
用布局类的布局管理有着更好的灵活性和实用性.它是更好的将部件放到一个窗口中的办法.QHBoxLayout和QVBoxLayout是基本的布局类,它会让部件们水平和垂直的对齐是.
想象一下,我们想把两个按钮放到右下角.要创建一个这样的布局,我们要用到一个水平和一个垂直框.为了创建必要的空间,我们要添加一下伸缩因子.
import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
QHBoxLayout, QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
okButton = QPushButton("OK")
cancelButton = QPushButton("Cancel")
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.setGeometry(300, 300, 300, 150)
self.setWindowTitle('Buttons')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
例子中我们在窗口的右下角放置了两个按钮.当我们调整程序窗口的大小时,它们的位置不变.我们用了一个HBoxLayout和一个QVBoxLayout.
okButton = QPushButton("OK")在此我们创建了两个按钮.
cancelButton = QPushButton("Cancel")
hbox = QHBoxLayout()我们创建一个水平方框布局,添加一个伸缩因子和两个按钮.伸缩因子在两个按钮以前被添加到一个可伸缩的空间.这会将它们放到窗口右侧.
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
vbox = QVBoxLayout()为了创建必要的布局,我们将水平布局加入到垂直布局中.在垂直布局中的伸缩因子会把带有按钮的水平框放到窗口下部.
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)最终,我们设置窗口的主布局.
图片:按钮
QGridLayout(网格布局)
最常用的布局类是网格布局.这个布局将空间分隔为行和列.要创建一个网络布局,我们会用QGridLayout这个类.
import sys
from PyQt5.QtWidgets import (QWidget, QGridLayout,
QPushButton, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
grid = 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 = QPushButton(name)
grid.addWidget(button, *position)
self.move(300, 150)
self.setWindowTitle('Calculator')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在这个例子中,我们创建了网格按钮.要填补一个空位,我们就添加一个QLabel部件.
grid = QGridLayout()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):按钮被创建并通过addWidget()方法被添加到布局中.
if name == '':
continue
button = QPushButton(name)
grid.addWidget(button, *position)
图片:计算器
复审例子
部件在网格中可以被分成多行多列.在下一个例子中我们会演示.import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit,
QTextEdit, QGridLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
title = QLabel('Title')
author = QLabel('Author')
review = QLabel('Review')
titleEdit = QLineEdit()
authorEdit = QLineEdit()
reviewEdit = QTextEdit()
grid = 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()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
我们创建一个带有三个标签的窗口,两个行行编辑器和一个文件编辑器部件.布局是通过QGridLayout完成的.
grid = QGridLayout()我们创建一个网格布局并设置部件之间的间距.
grid.setSpacing(10)
grid.addWidget(reviewEdit, 3, 1, 5, 1)如果我们添加一个部件到网格,我们可以提供部件的行宽和列宽.在这个例子中,我们用reviewEdit把部件分成5行.
图片:复审