ต่อจาก
บทที่ ๗
ในบทที่ผ่านมาได้พูดถึงการสร้าง widget และการจัดวาง widget ต่างๆลงในหน้าต่างโดยใช้ .setGeometry ไปแล้ว
ในบทนี้จะพูดถึงอีกวิธีการในการจัดวาง widget ลงบนหน้าต่าง นั่นคือการวางเป็นโครง layout โดยใช้ QHBoxLayout, QVBoxLayout หรือ QGridLayout ซึ่งอาจจะสะดวกกว่าการใส่ตัวเลขตั้งค่าตำแหน่งวางโดยตรง
การจัดวาง widget เป็นโครงตามแนวนอน {QHBoxLayout .setLayout .addWidget}
หากต้องการวาง widget ต่อกันตามแนวนอนอาจใช้ QHBoxLayout
วิธีการใช้นั้นเริ่มจากสร้างออบเจ็กต์ของคลาส QHBoxLayout ขึ้นมาใช้เมธอด .setLayout ที่ตัว widget หลักเพื่อตั้งตัว QHBoxLayout เป็นโครงของ widget นี้
จากนั้นก็ค่อยๆใส่ widget ที่เป็นส่วนประกอบทที่ต้องการวางในโครงลงไปใน QHBoxLayout ตัวนี้โดยใช้เมธอด .addWidget
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QHBoxLayout,QPushButton
qAp = QApplication(sys.argv)
natang = QWidget()
natang.setStyleSheet('''* {background-color: #cff;
font-family: Tahoma;
font-size: 21px}
QPushButton {background-color: #fcf;}''')
khrong = QHBoxLayout()
natang.setLayout(khrong)
p1 = QPushButton('ซ้าย')
p1.setFixedSize(150,50)
khrong.addWidget(p1)
p2 = QPushButton('กลาง')
p2.setFixedSize(70,150)
khrong.addWidget(p2)
p3 = QPushButton('ขวา')
p3.setFixedSize(90,90)
khrong.addWidget(p3)
natang.show()
qAp.exec_()
ก็จะได้ปุ่มที่จัดเรียงในลักษณะนี้
กรณีที่จัดวางด้วยโครง ขนาดของวัตถุจะกำหนดด้วย .resize หรือ .setGeometry ไม่ได้ ใช้ใช้ .setFixedSize แทน
การจัดหน้า {.setAlignment}
เมื่อใช้ QHBoxLayout เพื่อจัดวางตามแนวนอน widget แต่ละตัวจะถูกจัดให้ลอยอยู่ตรงกลาง แต่ถ้าหากต้องการจัดให้ไปอยู่ชิดบนหรือชิดล่างก็ทำได้โดยใช้ .setAlignment
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QHBoxLayout,QPushButton
from PyQt5.QtCore import Qt
qAp = QApplication(sys.argv)
natang = QWidget()
natang.setStyleSheet('QPushButton {background-color : #df6; font-size: 21px}')
khrong = QHBoxLayout()
natang.setLayout(khrong)
p1 = QPushButton('kami')
p1.setFixedSize(70,140)
khrong.addWidget(p1)
p2 = QPushButton('kame')
p2.setFixedSize(90,60)
khrong.addWidget(p2)
khrong.setAlignment(p2,Qt.AlignBottom) # ตั้งให้ไปอยู่ชิดล่าง
p3 = QPushButton('kama')
p3.setFixedSize(100,70)
khrong.addWidget(p3)
khrong.setAlignment(p3,Qt.AlignTop) # ตั้งให้ไปอยู่ชิดบน
p4 = QPushButton('kamo')
p4.setFixedSize(90,70)
khrong.addWidget(p4)
natang.show()
qAp.exec_()
จะได้ปุ่มที่จัดเรียงเป็นแบบนี้
การจัดวาง widget เป็นโครงตามแนวตั้ง {QVBoxLayout}
กรณีที่ต้องการจัดวางตามแนวตั้งจะใช้ QVBoxLayout ซึ่งวิธีใช้ก็คล้ายกับ QHBoxLayout แค่เปลี่ยนจากแนวนอนเป็นแนวตั้งเท่านั้นเอง
หากไม่ได้ตั้งการจัดเรียง ปกติ widget จะถูกจัดอยู่ชิดซ้าย ถ้าต้องการให้เรียงอยู่ตรงกลางก็ใช้ .setAlignment ได้เช่นกัน
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QVBoxLayout,QPushButton
from PyQt5.QtCore import Qt
qAp = QApplication(sys.argv)
natang = QWidget()
natang.setStyleSheet('font-family: Tahoma; font-size: 20px; color: #46c')
khrong = QVBoxLayout()
natang.setLayout(khrong)
p1 = QPushButton('เมฆ')
p1.setFixedSize(140,50)
khrong.addWidget(p1)
p2 = QPushButton('ฝน')
p2.setFixedSize(60,110)
khrong.addWidget(p2)
khrong.setAlignment(p2,Qt.AlignCenter) # ตั้งให้อยู่ตรงกลาง
p3 = QPushButton('รุ้ง')
p3.setFixedSize(100,70)
khrong.addWidget(p3)
khrong.setAlignment(p3,Qt.AlignRight) # ตั้งให้อยู่ชิดขวา
natang.show()
qAp.exec_()
จะได้ widget ปุ่มเรียงจากบนลงล่างแบบนี้
การจัดวางโครงซ้อนโครง {.addLayout}
QHBoxLayout กับ QVBoxLayout สามารถใช้ร่วมกันเพื่อสร้างโครงให้เรียงตามที่ต้องการได้
โดยอาจเริ่มเรียงจากแนวนอนเป็นหลักโดยใช้ QHBoxLayout แล้วก็ใช้เมธอด .addLayout เพื่อใส่โครง QVBoxLayout ลงไปอีกที หรือถ้าจะเรียงแนวตั้งก่อนก็กลับกัน
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QHBoxLayout,QVBoxLayout,QPushButton
from PyQt5.QtCore import Qt
qAp = QApplication(sys.argv)
natang = QWidget()
khrongtang = QVBoxLayout()
natang.setLayout(khrongtang)
khrongnon1 = QHBoxLayout()
khrongtang.addLayout(khrongnon1)
p1 = QPushButton('กาก')
p1.setFixedSize(60,60)
khrongnon1.addWidget(p1)
p2 = QPushButton('กาว')
p2.setFixedSize(90,90)
khrongnon1.addWidget(p2)
khrongnon2 = QHBoxLayout()
khrongtang.addLayout(khrongnon2)
p3 = QPushButton('กาบ')
p3.setFixedSize(70,110)
khrongnon2.addWidget(p3)
p4 = QPushButton('กาง')
p4.setFixedSize(110,70)
khrongnon2.addWidget(p4)
khrongnon2.setAlignment(p4,Qt.AlignBottom)
p5 = QPushButton('กาย')
p5.setFixedSize(50,80)
khrongnon2.addWidget(p5)
khrongnon2.setAlignment(p5,Qt.AlignTop)
p6 = QPushButton('กาด')
p6.setFixedSize(70,60)
khrongnon2.addWidget(p6)
natang.show()
qAp.exec_()
การใส่ช่องว่างเพื่อเว้น {.addStretch}
ปกติจะเห็นว่า widget ที่ถูกจัดอยู่ในโครงจะถูกจัดให้เว้นระยะพอๆกันตามความเหมาะสม แต่หากต้องการให้มีการเว้นช่วงไว้แล้วที่เหลือกวาดไปชิดขอบอีกด้าน อาจใช้ .addStretch
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QHBoxLayout,QVBoxLayout,QPushButton
qAp = QApplication(sys.argv)
natang = QWidget()
natang.setStyleSheet('font-size: 24px')
natang.setFixedSize(300,290)
khrongtang = QVBoxLayout()
natang.setLayout(khrongtang)
khrongnon1 = QHBoxLayout()
khrongtang.addLayout(khrongnon1)
p1 = QPushButton('ก')
p1.setFixedSize(50,50)
khrongnon1.addWidget(p1)
p2 = QPushButton('ข')
p2.setFixedSize(50,50)
khrongnon1.addWidget(p2)
khrongtang.addStretch()
khrongnon2 = QHBoxLayout()
khrongtang.addLayout(khrongnon2)
p3 = QPushButton('ค')
p3.setFixedSize(50,50)
khrongnon2.addWidget(p3)
khrongnon2.addStretch()
p4 = QPushButton('ง')
p4.setFixedSize(50,50)
khrongnon2.addWidget(p4)
khrongnon3 = QHBoxLayout()
khrongtang.addLayout(khrongnon3)
p5 = QPushButton('จ')
p5.setFixedSize(50,50)
khrongnon3.addWidget(p5)
p6 = QPushButton('ฉ')
p6.setFixedSize(50,50)
khrongnon3.addWidget(p6)
khrongnon3.addStretch()
natang.show()
qAp.exec_()
จะเห็นว่า .addStretch วางอยู่ตรงไหนตรงนั้นก็จะถูกเว้นว่าง
การจัดวาง widget เป็นตาราง {QGridLayout}
หากต้องการจัดวาง widget เป็นตารางอาจใช้ QGridLayout โดยเมื่อใช้ .addWidget เพื่อใส่ widget เข้าไปนั้นให้ใส่ตำแหน่งที่จะวางลงไปด้วย
ตัวโครงตาราง.addWidget(widget_ที่ต้องการวาง, ลำดับตามแนวนอน, ลำดับตามแนวตั้ง)
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QGridLayout,QPushButton
qAp = QApplication(sys.argv)
natang = QWidget()
natang.setStyleSheet('QPushButton {background-color: #9ff}')
khrong = QGridLayout()
natang.setLayout(khrong)
khrong.addWidget(QPushButton('ก k'),0,0)
khrong.addWidget(QPushButton('ต t'),0,1)
khrong.addWidget(QPushButton('บ b'),0,2)
khrong.addWidget(QPushButton('ป p'),1,0)
khrong.addWidget(QPushButton('ฟ f'),1,2)
khrong.addWidget(QPushButton('ม m'),2,1)
natang.show()
qAp.exec_()
สามารถใช้กับ for เพื่อวนซ้ำใส่ทีละหลายตัวได้สะดวก เช่น
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QGridLayout,QPushButton
from PyQt5.QtCore import Qt
qAp = QApplication(sys.argv)
natang = QWidget()
khrongtarang = QGridLayout()
natang.setLayout(khrongtarang)
for i in range(13):
for j in range(13):
pum = QPushButton()
pum.setFixedSize(20+((i+j+1)%2)*10,20+((i+j)%2)*10) # ตั้งขนาดปุ่มให้ต่างกันไป
si = 15+abs(i-6)*40,255-abs(j-6)*40,75+abs(j+i-12)*15 # ใส่สีต่างกันไป
pum.setStyleSheet('background-color: RGB(%d,%d,%d)'%si)
khrongtarang.addWidget(pum,i,j)
khrongtarang.setAlignment(pum,Qt.AlignCenter) # จัดหน้าให้อยู่กลาง
natang.show()
qAp.exec_()
สรุปท้ายบท
ในบทนี้ก็ได้แนะนำการนำ widget มาจัดวางเป็นโครงไปแล้ว ซึ่งก็มีทั้งการจัดวางในแนวตั้ง แนวนอน และเป็นตาราง
จะจัดวาง widget ด้วยโครงแบบในบทนี้หรือใช้ .setGeometry อย่างในบทที่ผ่านมาก็ได้ ตามความสะดวกหรือความถนัด
สำหรับในบทถัดไปก็จะใช้ทั้ง ๒ วิธีนี้สลับกันไป แล้วแต่ความเหมาะสมในแต่ละตัวอย่าง
อ่านบทถัดไป >>
บทที่ ๙