Layout 佈局 ( 垂直與水平 )
這篇教學會介紹如何透過 PyQt6 視窗裡的 QVBoxLayout() 和 QHBoxLayout() 方法,進行元件的垂直與水平佈局。
快速導覽:
因為 Google Colab 不支援 PyQt6,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda )。
建立 Layout 垂直與水平佈局
當 PyQt6 建立視窗後,視窗本身是一個 Widget,因此只要使用 QVBoxLayout() 和 QHBoxLayout() 方法,就可以在視窗 Widget 上建立垂直或水平佈局的「layout」,當 layout 建立後,只要放在該 layout 裡的元件,就會按照佈局的位置排列,無法透過 move() 或 setGeometry() 方法設定位置與大小。
下方的程式碼執行後,會在畫面左邊建立一個垂直 Layout,放入三顆按鈕,在畫面右邊建立一個水平 Layout,也放入三顆按鈕,在不做任何設定的狀況下,按鈕就會根據 Layout 的規範進行排列。
from PyQt6 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
# 垂直 Layout
vbox = QtWidgets.QWidget(Form) # 建立一個新的 Widget
vbox.setGeometry(0,0,150,150) # 設定 Widget 大小
v_layout = QtWidgets.QVBoxLayout(vbox) # 建立垂直 Layout
btn1 = QtWidgets.QPushButton(Form) # 在視窗中加入一個 QPushButton
btn1.setText('1') # 按鈕文字
v_layout.addWidget(btn1) # 將按鈕放入 v_layout 中
btn2 = QtWidgets.QPushButton(Form) # 在視窗中加入一個 QPushButton
btn2.setText('2') # 按鈕文字
v_layout.addWidget(btn2) # 將按鈕放入 v_layout 中
btn3 = QtWidgets.QPushButton(Form) # 在視窗中加入一個 QPushButton
btn3.setText('3') # 按鈕文字
v_layout.addWidget(btn3) # 將按鈕放入 v_layout 中
# 水平 Layout
hbox = QtWidgets.QWidget(Form) # 建立一個新的 Widget
hbox.setGeometry(150,0,150,150) # 設定 Widget 大小
h_layout = QtWidgets.QHBoxLayout(hbox) # 建立水平 Layout
btn4 = QtWidgets.QPushButton(Form) # 在視窗中加入一個 QPushButton
btn4.setText('4') # 按鈕文字
h_layout.addWidget(btn4) # 將按鈕放入 h_layout 中
btn5 = QtWidgets.QPushButton(Form) # 在視窗中加入一個 QPushButton
btn5.setText('5') # 按鈕文字
h_layout.addWidget(btn5) # 將按鈕放入 h_layout 中
btn6 = QtWidgets.QPushButton(Form) # 在視窗中加入一個 QPushButton
btn6.setText('6') # 按鈕文字
h_layout.addWidget(btn6) # 將按鈕放入 h_layout 中
Form.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets
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):
# 垂直 Layout
self.vbox = QtWidgets.QWidget(self) # 建立一個新的 Widget
self.vbox.setGeometry(0,0,150,150) # 設定 Widget 大小
self.v_layout = QtWidgets.QVBoxLayout(self.vbox) # 建立垂直 Layout
self.btn1 = QtWidgets.QPushButton(self) # 在視窗中加入一個 QPushButton
self.btn1.setText('1') # 按鈕文字
self.v_layout.addWidget(self.btn1) # 將按鈕放入 v_layout 中
self.btn2 = QtWidgets.QPushButton(self) # 在視窗中加入一個 QPushButton
self.btn2.setText('2') # 按鈕文字
self.v_layout.addWidget(self.btn2) # 將按鈕放入 v_layout 中
self.btn3 = QtWidgets.QPushButton(self) # 在視窗中加入一個 QPushButton
self.btn3.setText('3') # 按鈕文字
self.v_layout.addWidget(self.btn3) # 將按鈕放入 v_layout 中
# 水平 Layout
self.hbox = QtWidgets.QWidget(self) # 建立一個新的 Widget
self.hbox.setGeometry(150,0,150,150) # 設定 Widget 大小
self.h_layout = QtWidgets.QHBoxLayout(self.hbox) # 建立水平 Layout
self.btn4 = QtWidgets.QPushButton(self) # 在視窗中加入一個 QPushButton
self.btn4.setText('4') # 按鈕文字
self.h_layout.addWidget(self.btn4) # 將按鈕放入 h_layout 中
self.btn5 = QtWidgets.QPushButton(self) # 在視窗中加入一個 QPushButton
self.btn5.setText('5') # 按鈕文字
self.h_layout.addWidget(self.btn5) # 將按鈕放入 h_layout 中
self.btn6 = QtWidgets.QPushButton(self) # 在視窗中加入一個 QPushButton
self.btn6.setText('6') # 按鈕文字
self.h_layout.addWidget(self.btn6) # 將按鈕放入 h_layout 中
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
設定 Layout 裡元件的對齊方式
Layout 加入元件後,可以透過下列幾種對齊方法,設定元件的對齊方式 ( 用法和 PyQt5 相同但方法名稱不同 ):
對齊方式 | 說明 |
---|---|
QtCore.Qt.AlignmentFlag.AlignTop | 靠上對齊。 |
QtCore.Qt.AlignmentFlag.AlignBottom | 靠下對齊。 |
QtCore.Qt.AlignmentFlag.AlignCenter | 置中對齊。 |
QtCore.Qt.AlignmentFlag.AlignLeft | 靠左對齊。 |
QtCore.Qt.AlignmentFlag.AlignRight | 靠右對齊。 |
QtCore.Qt.AlignmentFlag.AlignVCenter | 垂直置中對齊。 |
QtCore.Qt.AlignmentFlag.AlignHCenter | 水平置中對齊。 |
下方的程式碼執行後,會將左側垂直排列的按鈕靠左對齊,將右側水平排列的按鈕靠上對齊。
from PyQt6 import QtWidgets, QtCore
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
# 垂直 Layout
vbox = QtWidgets.QWidget(Form)
vbox.setGeometry(0,0,150,150)
v_layout = QtWidgets.QVBoxLayout(vbox)
v_layout.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft) # 靠左對齊
btn1 = QtWidgets.QPushButton(Form)
btn1.setText('1')
v_layout.addWidget(btn1)
btn2 = QtWidgets.QPushButton(Form)
btn2.setText('2')
v_layout.addWidget(btn2)
btn3 = QtWidgets.QPushButton(Form)
btn3.setText('3')
v_layout.addWidget(btn3)
# 水平 Layout
hbox = QtWidgets.QWidget(Form)
hbox.setGeometry(150,0,150,150)
h_layout = QtWidgets.QHBoxLayout(hbox)
h_layout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) # 靠上對齊
btn4 = QtWidgets.QPushButton(Form)
btn4.setText('4')
h_layout.addWidget(btn4)
btn5 = QtWidgets.QPushButton(Form)
btn5.setText('5')
h_layout.addWidget(btn5)
btn6 = QtWidgets.QPushButton(Form)
btn6.setText('6')
h_layout.addWidget(btn6)
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):
self.vbox = QtWidgets.QWidget(self)
self.vbox.setGeometry(0,0,150,150)
self.v_layout = QtWidgets.QVBoxLayout(self.vbox)
self.v_layout.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft) # 靠左對齊
self.btn1 = QtWidgets.QPushButton(self)
self.btn1.setText('1')
self.v_layout.addWidget(self.btn1)
self.btn2 = QtWidgets.QPushButton(self)
self.btn2.setText('2')
self.v_layout.addWidget(self.btn2)
self.btn3 = QtWidgets.QPushButton(self)
self.btn3.setText('3')
self.v_layout.addWidget(self.btn3)
self.hbox = QtWidgets.QWidget(self)
self.hbox.setGeometry(150,0,150,150)
self.h_layout = QtWidgets.QHBoxLayout(self.hbox)
self.h_layout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) # 靠上對齊
self.btn4 = QtWidgets.QPushButton(self)
self.btn4.setText('4')
self.h_layout.addWidget(self.btn4)
self.btn5 = QtWidgets.QPushButton(self)
self.btn5.setText('5')
self.h_layout.addWidget(self.btn5)
self.btn6 = QtWidgets.QPushButton(self)
self.btn6.setText('6')
self.h_layout.addWidget(self.btn6)
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, QtCore
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
# 設定放置 Layout 的 Widget 樣式
style_box = '''
background:#fff;
border:1px solid #000;
'''
# 設定按鈕樣式
style_btn = '''
QPushButton{
background:#ff0;
border:1px solid #000;
border-radius:10px;
padding:5px;
}
QPushButton:pressed{
background:#f90;
}
'''
# 垂直 Layout
vbox = QtWidgets.QWidget(Form)
vbox.setGeometry(0,0,120,120)
vbox.setStyleSheet(style_box)
v_layout = QtWidgets.QVBoxLayout(vbox)
v_layout.setAlignment(QtCore.Qt.AlignLeft) # 靠左對齊
btn1 = QtWidgets.QPushButton(Form)
btn1.setText('1')
btn1.setStyleSheet(style_btn)
v_layout.addWidget(btn1)
btn2 = QtWidgets.QPushButton(Form)
btn2.setText('2')
btn2.setStyleSheet(style_btn)
v_layout.addWidget(btn2)
btn3 = QtWidgets.QPushButton(Form)
btn3.setText('3')
btn3.setStyleSheet(style_btn)
v_layout.addWidget(btn3)
# 水平 Layout
hbox = QtWidgets.QWidget(Form)
hbox.setGeometry(130,0,120,120)
hbox.setStyleSheet(style_box)
h_layout = QtWidgets.QHBoxLayout(hbox)
h_layout.setAlignment(QtCore.Qt.AlignTop) # 靠上對齊
btn4 = QtWidgets.QPushButton(Form)
btn4.setText('4')
btn4.setStyleSheet(style_btn)
h_layout.addWidget(btn4)
btn5 = QtWidgets.QPushButton(Form)
btn5.setText('5')
btn5.setStyleSheet(style_btn)
h_layout.addWidget(btn5)
btn6 = QtWidgets.QPushButton(Form)
btn6.setText('6')
btn6.setStyleSheet(style_btn)
h_layout.addWidget(btn6)
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):
# 設定放置 Layout 的 Widget 樣式
style_box = '''
background:#fff;
border:1px solid #000;
'''
# 設定按鈕樣式
style_btn = '''
QPushButton{
background:#ff0;
border:1px solid #000;
border-radius:10px;
padding:5px;
}
QPushButton:pressed{
background:#f90;
}
'''
# 垂直 Layout
self.vbox = QtWidgets.QWidget(self)
self.vbox.setGeometry(0,0,120,120)
self.vbox.setStyleSheet(style_box)
self.v_layout = QtWidgets.QVBoxLayout(self.vbox)
self.v_layout.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft) # 靠左對齊
self.btn1 = QtWidgets.QPushButton(self)
self.btn1.setText('1')
self.btn1.setStyleSheet(style_btn)
self.v_layout.addWidget(self.btn1)
self.btn2 = QtWidgets.QPushButton(self)
self.btn2.setText('2')
self.btn2.setStyleSheet(style_btn)
self.v_layout.addWidget(self.btn2)
self.btn3 = QtWidgets.QPushButton(self)
self.btn3.setText('3')
self.btn3.setStyleSheet(style_btn)
self.v_layout.addWidget(self.btn3)
# 水平 Layout
self.hbox = QtWidgets.QWidget(self)
self.hbox.setGeometry(130,0,120,120)
self.hbox.setStyleSheet(style_box)
self.h_layout = QtWidgets.QHBoxLayout(self.hbox)
self.h_layout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) # 靠上對齊
self.btn4 = QtWidgets.QPushButton(self)
self.btn4.setText('4')
self.btn4.setStyleSheet(style_btn)
self.h_layout.addWidget(self.btn4)
self.btn5 = QtWidgets.QPushButton(self)
self.btn5.setText('5')
self.btn5.setStyleSheet(style_btn)
self.h_layout.addWidget(self.btn5)
self.btn6 = QtWidgets.QPushButton(self)
self.btn6.setText('6')
self.btn6.setStyleSheet(style_btn)
self.h_layout.addWidget(self.btn6)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~