Layout 佈局 ( Gird 網格 )
這篇教學會介紹如何透過 PyQt5 視窗裡的 QGridLayout() 方法,進行元件的 Grid 網格佈局。
快速導覽:
- PyQt6 版本參考:PyQt6 教學 - Layout 佈局 ( Gird 網格 )
- 因為 Google Colab 不支援 PyQt5,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda )。
建立 Gird 網格佈局
當 PyQt5 建立視窗後,視窗本身是一個 Widget,因此只要使用 QGridLayout() 方法,就可以在視窗 Widget 上建立 Grid 網格佈局的「layout」,當 layout 建立後,只要放在該 layout 裡的元件,就會按照指定的 grid 位置排列,無法透過 move() 或 setGeometry() 方法設定位置與大小。
下方的程式碼執行後,會在畫面先建立一個 QGirdLayout,並放入六顆按鈕,排列成 3x2 的位置。
使用
addWidget(Widget, row, column)
放入按鈕時,可以指定對應的 row ( 垂直 ) 和 column ( 水平 ) 位置,左上角從 0 開始。
from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
box = QtWidgets.QWidget(Form) # 建立放 QGridLayout 的元件
box.setGeometry(10,10,150,150) # 指定大小位置
grid = QtWidgets.QGridLayout(box) # 建立 QGridLayout
btn1 = QtWidgets.QPushButton(Form) # 建立按鈕
btn1.setText('1')
grid.addWidget(btn1, 0, 0) # 按鈕放在 (0, 0) 位置
btn2 = QtWidgets.QPushButton(Form) # 建立按鈕
btn2.setText('2')
grid.addWidget(btn2, 0, 1) # 按鈕放在 (0, 1) 位置
btn3 = QtWidgets.QPushButton(Form) # 建立按鈕
btn3.setText('3')
grid.addWidget(btn3, 0, 2) # 按鈕放在 (0, 2) 位置
btn4 = QtWidgets.QPushButton(Form) # 建立按鈕
btn4.setText('4')
grid.addWidget(btn4, 1, 0) # 按鈕放在 (1, 0) 位置
btn5 = QtWidgets.QPushButton(Form) # 建立按鈕
btn5.setText('5')
grid.addWidget(btn5, 1, 1) # 按鈕放在 (1, 1) 位置
btn6 = QtWidgets.QPushButton(Form) # 建立按鈕
btn6.setText('6')
grid.addWidget(btn6, 1, 2) # 按鈕放在 (1, 2) 位置
Form.show()
sys.exit(app.exec_())
合併 Gird 網格
如果在 addWidget() 方法例額外設定第四個與第五個參數,就能處理「跨網格 ( 合併網格 )」的狀況,第四個參數為垂直合併的網格數量,第五個參數為水平合併的網格數量,以下方的程式碼為例,第四顆按鈕將第四個與第五個參數設定為 1 和 3,表示垂直維持一格,水平則合併三格。
from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
box = QtWidgets.QWidget(Form)
box.setGeometry(10,10,150,150)
grid = QtWidgets.QGridLayout(box)
btn1 = QtWidgets.QPushButton(Form)
btn1.setText('1')
grid.addWidget(btn1, 0, 0)
btn2 = QtWidgets.QPushButton(Form)
btn2.setText('2')
grid.addWidget(btn2, 0, 1)
btn3 = QtWidgets.QPushButton(Form)
btn3.setText('3')
grid.addWidget(btn3, 0, 2)
btn4 = QtWidgets.QPushButton(Form)
btn4.setText('4')
grid.addWidget(btn4, 1, 0, 1, 3) # 垂直一格,水平三格
Form.show()
sys.exit(app.exec_())
調整 Layout 樣式
建立放置 Layout 的 Widget 後,可以針對這個 Widget 使用 setStyleSheet()
方法設定樣式,但需要注意的是,一但設定這個 Widget 樣式,會連帶影響到裡頭的元件樣式,因此如果需要設定樣式,要連同裡面的元件一併進行設定,以下方的程式碼為例,將放置 Layout 的 Widget 設定為白底黑框後,需要額外設定按鈕的樣式,否則按鈕的預設樣式就會消失。
from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
style_box = '''
background:#fff;
border:1px solid #000;
'''
style_btn = '''
background:#ff0;
padding:5px;
border-radius:4px;
'''
box = QtWidgets.QWidget(Form)
box.setGeometry(10,10,150,150)
box.setStyleSheet(style_box)
grid = QtWidgets.QGridLayout(box)
btn1 = QtWidgets.QPushButton(Form)
btn1.setText('1')
btn1.setStyleSheet(style_btn)
grid.addWidget(btn1, 0, 0)
btn2 = QtWidgets.QPushButton(Form)
btn2.setText('2')
grid.addWidget(btn2, 0, 1)
btn3 = QtWidgets.QPushButton(Form)
btn3.setText('3')
grid.addWidget(btn3, 0, 2)
btn4 = QtWidgets.QPushButton(Form)
btn4.setText('4')
grid.addWidget(btn4, 1, 0, 1, 3)
Form.show()
sys.exit(app.exec_())
Layout 裡放入 Layout
使用 addWidget()
方法可以加入元件,使用 addItem()
方法可以在 Layout 裡加入其他 Layout,下方的程式碼執行後,會在第二列合併三格的網格裡,加入一個包含兩顆按鈕的 QGridLayout。
from PyQt5 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
box = QtWidgets.QWidget(Form)
box.setGeometry(10,10,150,150)
grid = QtWidgets.QGridLayout(box)
btn1 = QtWidgets.QPushButton(Form)
btn1.setText('1')
grid.addWidget(btn1, 0, 0)
btn2 = QtWidgets.QPushButton(Form)
btn2.setText('2')
grid.addWidget(btn2, 0, 1)
btn3 = QtWidgets.QPushButton(Form)
btn3.setText('3')
grid.addWidget(btn3, 0, 2)
grid2 = QtWidgets.QGridLayout(box) # 新建一個 QGridLayout
grid.addItem(grid2, 1, 0, 1, 3) # 使用 addItem 方法
btn4 = QtWidgets.QPushButton(Form)
btn4.setText('4')
grid2.addWidget(btn4, 0, 0) # 新的 QGridLayout 加入按鈕
btn5 = QtWidgets.QPushButton(Form)
btn5.setText('5')
grid2.addWidget(btn5, 0, 1) # 新的 QGridLayout 加入按鈕
Form.show()
sys.exit(app.exec_())
改用 class 的寫法
上方的程式碼,亦可改用 class 的寫法表示。
from PyQt5 import QtWidgets
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
self.box = QtWidgets.QWidget(self)
self.box.setGeometry(10,10,150,150)
self.grid = QtWidgets.QGridLayout(self.box)
self.btn1 = QtWidgets.QPushButton(self)
self.btn1.setText('1')
self.grid.addWidget(self.btn1, 0, 0)
self.btn2 = QtWidgets.QPushButton(self)
self.btn2.setText('2')
self.grid.addWidget(self.btn2, 0, 1)
self.btn3 = QtWidgets.QPushButton(self)
self.btn3.setText('3')
self.grid.addWidget(self.btn3, 0, 2)
self.grid2 = QtWidgets.QGridLayout(self.box)
self.grid.addItem(self.grid2, 1, 0, 1, 3)
self.btn4 = QtWidgets.QPushButton(self)
self.btn4.setText('4')
self.grid2.addWidget(self.btn4, 0, 0)
self.btn5 = QtWidgets.QPushButton(self)
self.btn5.setText('5')
self.grid2.addWidget(self.btn5, 0, 1)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec_())
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~