pyqt5之佈局管理

佈局管理

在一個GUI程序裏,佈局是一個很重要的方面。佈局就是如何管理應用中的元素和窗口。有兩種方式可以搞定:絕對定位和PyQt5的layout類

絕對定位

每個程序都是以像素爲單位區分元素的位置,衡量元素的大小。所以我們完全可以使用絕對定位搞定每個元素和窗口的位置。但是這也有侷限性:

  • 元素不會隨着我們更改窗口的位置和大小而變化。
  • 不能適用於不同的平臺和不同分辨率的顯示器
  • 更改應用字體大小會破壞佈局
  • 如果我們決定重構這個應用,需要全部計算一下每個元素的位置和大小

下面這個就是絕對定位的應用

""""
brief:絕對定位
程序指定每個控件的位置和大小(以像素爲單位)。
絕對定位有以下限制:
    如果我們調整窗口,控件的大小和位置不會改變
    在各種平臺上應用程序看起來會不一樣
    如果改變字體,我們的應用程序的佈局就會改變
    如果我們決定改變我們的佈局,我們必須完全重做我們的佈局
author:chenyijun
date:2020-01-26
"""
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        label1 = QLabel("Zetcode", self)
        label1.move(15, 10)

        label2 = QLabel("Tutorials", self)
        label2.move(35, 40)

        label3 = QLabel("for programmers", self)
        label3.move(55, 70)

        self.setGeometry(300, 300, 350, 150)
        self.setWindowTitle("Absolute")
        self.show()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

我們使用move()方法定位了每一個元素,使用x、y座標。x、y座標的原點是程序的左上角。

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

這個元素的左上角就在這個程序的左上角開始的(15, 10)的位置。

程序展示:

 

盒佈局

使用盒佈局能讓程序具有更強的適應性。這個纔是佈局一個應用的更合適的方式。QHBoxLayout和QVBoxLayout是基本的佈局類,分別是水平佈局和垂直佈局。

如果我們需要把兩個按鈕放在程序的右下角,創建這樣的佈局,我們只需要一個水平佈局加一個垂直佈局的盒子就可以了。再用彈性佈局增加一點間隙。

""""
brief:框佈局 Boxlayout
我們使用QHBoxLayout和QVBoxLayout,來分別創建橫向佈局和縱向佈局。
author:chenyijun
date:2020-01-26
"""
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, 350, 150)
        self.setWindowTitle("Buttons")
        self.show()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = Example();
    sys.exit(app.exec_())

上面的例子完成了在應用的右下角放了兩個按鈕的需求。當改變窗口大小的時候,它們能依然保持在相對的位置。我們同時使用了QHBoxLayout和QVBoxLayout。

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

這是創建了兩個按鈕。

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

創建一個水平佈局,增加兩個按鈕和彈性空間。stretch函數在兩個按鈕前面增加了一些彈性空間。下一步我們把這些元素放在應用的右下角。

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

爲了佈局需要,我們把這個水平佈局放到了一個垂直佈局盒裏面。彈性元素會把所有的元素一起都放置在應用的右下角。

self.setLayout(vbox)

最後,我們就得到了我們想要的佈局。

程序預覽:

柵格佈局

最常用的還是柵格佈局了。這種佈局是把窗口分爲行和列。創建和使用柵格佈局,需要使用QGridLayout模塊。

""""
brief:表格佈局 QGridLayout
表格佈局將空間劃分爲行和列。我們使用QGridLayout類創建一個網格佈局。
author:chenyijun
date:2020-01-26
"""
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(350, 150)
        self.setWindowTitle("Calculator")
        self.show()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = Example();
    sys.exit(app.exec_())

這個例子裏,我們創建了柵格化的按鈕。

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()方法把按鈕放到佈局裏面。

程序預覽:

製作提交反饋信息的佈局

組件能跨列和跨行展示,這個例子裏,我們就試試這個功能。

""""
brief:評論的例子
控件可以在網格中跨越多個行或列。在下一個示例中,我們說明了這一點。
author:chenyijun
date:2020-01-26
"""

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

我們可以指定組件的跨行和跨列的大小。這裏我們指定這個元素跨5行顯示。

程序預覽:

參考:

https://maicss.gitbooks.io/pyqt5/

http://zetcode.com/gui/pyqt5/

http://code.py40.com/pyqt5/

 

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