【第三節】PyQt5佈局管理
PyQt5佈局有兩種方式,絕對定位和佈局類
絕對定位
程式指定每個控制元件的位置和大小(以畫素為單位)。
絕對定位有以下限制:
- 如果我們調整視窗,控制元件的大小和位置不會改變
- 在各種平臺上應用程式看起來會不一樣
- 如果改變字型,我們的應用程式的佈局就會改變
- 如果我們決定改變我們的佈局,我們必須完全重做我們的佈局
下面的例子顯示了一個絕對定位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#!/usr/bin/python3 # -*- coding: utf-8 -*- """ Py40 PyQt5 tutorial This example shows three labels on a window using absolute positioning. author: Jan Bodnar website: py40.com last edited: January 2015 """ 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_()) |
我們使用move()方法來控制控制元件的位置。
框佈局 Boxlayout
我們使用QHBoxLayout和QVBoxLayout,來分別建立橫向佈局和縱向佈局。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#!/usr/bin/python3 # -*- coding: utf-8 -*- """ Py40 PyQt5 tutorial In this example, we position two push buttons in the bottom-right corner of the window. author: Jan Bodnar website: py40.com last edited: January 2015 """ 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並新增伸展因子,在視窗的右下角顯示兩個按鈕。
1 2 3 4 |
hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(okButton) hbox.addWidget(cancelButton) |
我們建立一個水平佈局和新增一個伸展因子和兩個按鈕。兩個按鈕前的伸展增加了一個可伸縮的空間。這將推動他們靠右顯示。
1 2 3 |
vbox = QVBoxLayout() vbox.addStretch(1) vbox.addLayout(hbox) |
建立一個垂直佈局,並新增伸展因子,讓水平佈局顯示在視窗底部
1 |
self.setLayout(vbox) |
最後,我們設定視窗的佈局介面
表格佈局 QGridLayout
表格佈局將空間劃分為行和列。我們使用QGridLayout類建立一個網格佈局。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#!/usr/bin/python3 # -*- coding: utf-8 -*- """ Py40 PyQt5 tutorial In this example, we create a skeleton of a calculator using a QGridLayout. author: Jan Bodnar website: py40.com last edited: January 2015 """ 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_()) |
在我們的示例中,我們建立一個網格的按鈕。
1 2 |
grid = QGridLayout() self.setLayout(grid) |
QGridLayout的例項被建立並設定應用程式視窗的佈局。
1 2 3 4 5 |
names = ['Cls', 'Bck', '', 'Close', '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '0', '.', '=', '+'] |
這些按鈕的標籤。
1 |
positions = [(i,j) for i in range(5) for j in range(4)] |
我們建立一個網格中的位置的列表。
1 2 3 4 5 6 |
for position, name in zip(positions, names): if name == '': continue button = QPushButton(name) grid.addWidget(button, *position) |
建立按鈕並使用addWidget()方法新增到佈局中。
評論的例子
控制元件可以在網格中跨越多個行或列。在下一個示例中,我們說明了這一點。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
#!/usr/bin/python3 # -*- coding: utf-8 -*- """ Py40 PyQt5 tutorial In this example, we create a bit more complicated window layout using the QGridLayout manager. author: Jan Bodnar website: py40.com last edited: January 2015 """ 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完成佈局。
1 2 |
grid = QGridLayout() grid.setSpacing(10) |
建立一個網格佈局和設定元件之間的間距。
1 |
grid.addWidget(reviewEdit, 3, 1, 5, 1) |
在新增一個小的控制元件到網格的時候,我們可以提供小部件的行和列跨。在例子中,reviewEdit控制元件跨度5行。