Layout 布局 ( Grid 网格 )
这篇教学会介绍如何透过 PyQt6 视窗里的 QGridLayout() 方法,进行元件的 Grid 网格布局。
快速导览:
因为 Google Colab 不支援 PyQt6,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda )。
建立 Gird 网格布局
当 PyQt6 建立视窗后,视窗本身是一个 Widget,因此只要使用 QGridLayout() 方法,就可以在视窗 Widget 上建立 Grid 网格布局的“layout”,当 layout 建立后,只要放在该 layout 里的元件,就会按照指定的 grid 位置排列,无法透过 move() 或 setGeometry() 方法设定位置与大小。
下方的程序码执行后,会在画面先建立一个 QGirdLayout,并放入六颗按钮,排列成 3x2 的位置。
使用
addWidget(Widget, row, column)放入按钮时,可以指定对应的 row ( 垂直 ) 和 column ( 水平 ) 位置,左上角从 0 开始。
from PyQt6 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())
class 写法:
from PyQt6 import QtWidgets, QtCore
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
box = QtWidgets.QWidget(self) # 建立放 QGridLayout 的元件
box.setGeometry(10,10,150,150) # 指定大小位置
grid = QtWidgets.QGridLayout(box) # 建立 QGridLayout
btn1 = QtWidgets.QPushButton(self) # 建立按鈕
btn1.setText('1')
grid.addWidget(btn1, 0, 0) # 按鈕放在 (0, 0) 位置
btn2 = QtWidgets.QPushButton(self) # 建立按鈕
btn2.setText('2')
grid.addWidget(btn2, 0, 1) # 按鈕放在 (0, 1) 位置
btn3 = QtWidgets.QPushButton(self) # 建立按鈕
btn3.setText('3')
grid.addWidget(btn3, 0, 2) # 按鈕放在 (0, 2) 位置
btn4 = QtWidgets.QPushButton(self) # 建立按鈕
btn4.setText('4')
grid.addWidget(btn4, 1, 0) # 按鈕放在 (1, 0) 位置
btn5 = QtWidgets.QPushButton(self) # 建立按鈕
btn5.setText('5')
grid.addWidget(btn5, 1, 1) # 按鈕放在 (1, 1) 位置
btn6 = QtWidgets.QPushButton(self) # 建立按鈕
btn6.setText('6')
grid.addWidget(btn6, 1, 2) # 按鈕放在 (1, 2) 位置
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
合并 Gird 网格
如果在 addWidget() 方法例额外设定第四个与第五个参数,就能处理“跨网格 ( 合并网格 )”的状况,第四个参数为垂直合并的网格数量,第五个参数为水平合并的网格数量,以下方的程序码为例,第四颗按钮将第四个与第五个参数设定为 1 和 3,表示垂直维持一格,水平则合并三格。
from PyQt6 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())
class 写法:
from PyQt6 import QtWidgets, QtCore
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
box = QtWidgets.QWidget(self)
box.setGeometry(10,10,150,150)
grid = QtWidgets.QGridLayout(box)
btn1 = QtWidgets.QPushButton(self)
btn1.setText('1')
grid.addWidget(btn1, 0, 0)
btn2 = QtWidgets.QPushButton(self)
btn2.setText('2')
grid.addWidget(btn2, 0, 1)
btn3 = QtWidgets.QPushButton(self)
btn3.setText('3')
grid.addWidget(btn3, 0, 2)
btn4 = QtWidgets.QPushButton(self)
btn4.setText('4')
grid.addWidget(btn4, 1, 0, 1, 3) # 垂直一格,水平三格
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
调整 Layout 样式
建立放置 Layout 的 Widget 后,可以针对这个 Widget 使用 setStyleSheet() 方法设定样式,但需要注意的是,一但设定这个 Widget 样式,会连带影响到里头的元件样式,因此如果需要设定样式,要连同里面的元件一并进行设定,以下方的程序码为例,将放置 Layout 的 Widget 设定为白底黑框后,需要额外设定按钮的样式,否则按钮的默认样式就会消失。
from PyQt6 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())
class 写法:
from PyQt6 import QtWidgets, QtCore
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
style_box = '''
background:#fff;
border:1px solid #000;
'''
style_btn = '''
background:#ff0;
padding:5px;
border-radius:4px;
'''
box = QtWidgets.QWidget(self)
box.setGeometry(10,10,150,150)
box.setStyleSheet(style_box)
grid = QtWidgets.QGridLayout(box)
btn1 = QtWidgets.QPushButton(self)
btn1.setText('1')
btn1.setStyleSheet(style_btn)
grid.addWidget(btn1, 0, 0)
btn2 = QtWidgets.QPushButton(self)
btn2.setText('2')
grid.addWidget(btn2, 0, 1)
btn3 = QtWidgets.QPushButton(self)
btn3.setText('3')
grid.addWidget(btn3, 0, 2)
btn4 = QtWidgets.QPushButton(self)
btn4.setText('4')
grid.addWidget(btn4, 1, 0, 1, 3)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
Layout 里放入 Layout
使用 addWidget() 方法可以加入元件,使用 addItem() 方法可以在 Layout 里加入其他 Layout,下方的程序码执行后,会在第二列合并三格的网格里,加入一个包含两颗按钮的 QGridLayout。
from PyQt6 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 的写法:
from PyQt6 import QtWidgets, QtCore
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
box = QtWidgets.QWidget(self)
box.setGeometry(10,10,150,150)
grid = QtWidgets.QGridLayout(box)
btn1 = QtWidgets.QPushButton(self)
btn1.setText('1')
grid.addWidget(btn1, 0, 0)
btn2 = QtWidgets.QPushButton(self)
btn2.setText('2')
grid.addWidget(btn2, 0, 1)
btn3 = QtWidgets.QPushButton(self)
btn3.setText('3')
grid.addWidget(btn3, 0, 2)
grid2 = QtWidgets.QGridLayout(box) # 新建一個 QGridLayout
grid.addItem(grid2, 1, 0, 1, 3) # 使用 addItem 方法
btn4 = QtWidgets.QPushButton(self)
btn4.setText('4')
grid2.addWidget(btn4, 0, 0) # 新的 QGridLayout 加入按鈕
btn5 = QtWidgets.QPushButton(self)
btn5.setText('5')
grid2.addWidget(btn5, 0, 1) # 新的 QGridLayout 加入按鈕
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
微信扫码关注
抖音扫码关注