PyQt5初级教程--PyQt5中的布局管理[5/13]

时间:2021-04-22 22:58:41
想用PyQt5写GUI,但是网上的PyQt5资源太少了,找到一个英文的,翻译一下,和学习PyQt5的同学共勉!

(本系列中所有代码在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)
lbl1.move(15, 10)
标签部件定位在x=15,y=10的位置.

PyQt5初级教程--PyQt5中的布局管理[5/13]

图片:绝对定位

框布局

用布局类的布局管理有着更好的灵活性和实用性.它是更好的将部件放到一个窗口中的办法.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)
最终,我们设置窗口的主布局.

PyQt5初级教程--PyQt5中的布局管理[5/13]

图片:按钮

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()
self.setLayout(grid)
QGridLayout的实例被创建,并设置为程序窗口的布局.

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)
按钮被创建并通过addWidget()方法被添加到布局中.

PyQt5初级教程--PyQt5中的布局管理[5/13]

图片:计算器

复审例子

部件在网格中可以被分成多行多列.在下一个例子中我们会演示.

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行.

PyQt5初级教程--PyQt5中的布局管理[5/13]

图片:复审