PyQt4入门教程(4)_布局管理

注:文中译者自己的话将用方括号【】标出。

布局管理(Layout management)是GUI编程中一个重要的方面。布局是我们将各种部件摆放在窗口中的方式。在PyQt4中,布局可以通过两种方式实现:绝对定位(absolute positioning)和layout类。

绝对定位

在这种方式中,编程者指定各种部件的位置和大小。但是当你使用绝对定位时,需要知道有以下的限制:
- 如果我们改变窗口的大小,部件的大小和位置并不会改变。
- 你的应用在不同平台下可能长得不太一样。
- 改变应用中使用的字体可能会扰乱布局。
- 如果我们想改变现有的布局的话,我们必须完全重写布局,这很乏味而且浪费时间。
下面这个例子将使用绝对座标来定位部件:

# -*- coding: utf-8 -*-

"""
This example shows three labels on a window
using absolute positioning. 
"""

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

我们使用move()方法来定位部件,在这个例子中我们定位了标签(label)。我们通过提供精确的x、y座标来实现定位。注意,原点是左上角,x值从左到右增加,y值从上到下增加。【注意到这里标签移动到的位置是相对于我们建立的窗口的左上角的】

lbl1 = QtGui.QLabel('Zetcode', self)
lbl1.move(15, 10)

这里标签就被定位到了x=15、y=10的地方。
效果如下:
absolute positioning

盒布局(Box layout)

用layout类实现的布局操作更加灵活和现实,这种方式是我们在窗口中定位部件的一种更推荐使用的方式。其中QtGui.QHBoxLayout和QtGui.QVBoxLayout是最基本的layout类,它们可以将部件水平或垂直排列。
假设我们想要在窗口的右下角放置两个按钮。为了做到这样的布局,我们将会用到一个水平盒子(horizontal box)和一个垂直盒子(vertical box)。为了创造必须的空间,我们加入了一个拉伸系数(stretch factor)【这里看不懂没关系,下面会讲】。

# -*- coding: utf-8 -*-

"""
In this example, we position two push
buttons in the bottom-right corner 
of the window. 
"""

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('Buttons')    
        self.show()

def main():

    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

这个例子中我们将两个按钮放在了窗口的右下角。即使我们改变窗口的大小,它们也会在那个地方。

okButton = QtGui.QPushButton("OK")
cancelButton = QtGui.QPushButton("Cancel")

这里我们创建了两个按钮(push button)。

hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)

这里我们创建了一个水平盒子,并给两个按钮增加了一个伸展系数。伸展系数可以给两个按钮前方创造一个可以伸展的空间,这样两个按钮就被挤到了水平盒子的右边,也就呈现在了窗口的右边。

vbox = QtGui.QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)

我们这里将之前创建的水平盒子放进了一个垂直盒子里面【为什么要这样做呢?因为要把水平盒子挤到下面去!】。这里的伸展系数将水平盒子挤到了垂直盒子的下方,也就呈现在了屏幕的下方。【经过两次挤压,按钮现在就在窗口的右下方啦!大家可以自己试一下不加伸展因子是什么样子的,还要改变窗口大小试一试!】

self.setLayout(vbox)

最终,我们将垂直盒子设置成窗口的布局形式。
最后效果是这样子的:
buttons

网格布局:QtGui.QGridLayout类

最普遍使用的布局类是网格布局(grid layout),这种布局将空间分成行和列。为了创造网格布局,我们使用QtGui.QGridLayout类。
下面这个例子中,我们将使用网格布局创建一个计算器的框架。

# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui

"""
In this example, we create a skeleton
of a calculator using a QtGui.QGridLayout.
"""

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

在这个例子中,我们创建了许多位于网格中的按钮。

grid = QtGui.QGridLayout()
self.setLayout(grid)

这里我们创建了QtGui.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 = QtGui.QPushButton(name)
    grid.addWidget(button, *position)

这里我们创建了按钮并且用addWidget()方法将它们加入了表格中。
最终效果是这样子的:
calculator

一个书评窗口的例子

部件可以在表格中占据多行多列,下面这个例子中我们将会说明这一点。

# -*- coding: utf-8 -*-

"""
In this example, we create a bit
more complicated window layout using
the QtGui.QGridLayout manager. 
"""

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

我们创建了一个拥有三个标签、两个行编辑框(line edit)和一个文本编辑框(text edit)的一个窗口,并且通过QtGui.QGridLayout来实现布局。

grid = QtGui.QGridLayout()
grid.setSpacing(10)

这里我们创建了一个网格布局,设定了两个部件之间的间距。

grid.addWidget(reviewEdit, 3, 1, 5, 1)

如果我们要把一个部件加入网格,我们可以提供行跨距和列跨局作为后两个参数,这里我们使reviewEdit部件占据了5行。
最后的效果是这样的:
review

本节就这么多内容,这一部分我们学习了PyQt4的布局管理操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章