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的佈局管理操作。

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