ต่อจาก
บทที่ ๑๙
ในบทนี้จะเป็นเรื่องของการสร้างและใช้งาน QMainWindow ซึ่งเป็นหน้าต่างที่มีส่วนประกอบต่างๆพร้อม เหมาะกับใช้ทำอะไรหลายๆอย่าง
การสร้างหน้าต่างหลัก {QMainWindow}
ในบทที่ผ่านมาเราใช้ QWidget เพื่อสร้าง widget ตัวเริ่มแรกสุดที่ใช้เป็นหน้าต่าง แต่จริงๆแล้ว widget อื่นๆก็เป็นซับคลาสของ QWidget ดังนั้นก็ใช้เป็นหน้าต่างได้เช่นกัน เช่นพวกกล่องเด้งแสดงข้อความหรือกล่องป้อนข้อมูลดังที่เขียนถึงใน
บทที่ ๑๗,
๑๘ และ
๑๙
นอกจากนี้ก็ยังมี widget ตัวหนึ่งที่ถูกออกแบบมาเพื่อใช้เป็นหน้าต่างหลักที่ใส่องค์ประกอบต่างๆที่มักใช้ใน GUI ลงไปเพิ่มเติมได้หลายอย่าง นั่นคือ QMainWindow
QMainWindow ประกอบด้วยส่วนประกอบต่างๆดังนี้
central widget | widget หลักส่วนใจกลางของหน้าต่าง |
status bar | แถบสถานะซึ่งอยู่ด้านล่าง |
dock widget | แถบประกบที่อาจวางอยู่ด้านบนล่างซ้ายขวาหรือส่วนมุม หรืออาจเป็นหน้าต่างลอยแยก สามารถย้ายตำแหน่งได้ |
menu bar | แถบเมนูที่อยู่ด้านบน ซึ่งคลิกแล้วจะมีแถบตัวเลือกย่อยโผล่ขึ้นมาให้เลือก |
toolbar | แถบเครื่องมือที่เอาไว้วางพวกปุ่มสำคัญ มักอยู่ด้านบน ใต้แถบเมนู แต่สามารถย้ายได้ |
ลองวาดเป็นภาพจะได้ประมาณนี้
menu bar |
toolbar |
| dock widget | |
dock widget | central widget | dock widget |
| dock widget | |
status bar |
ต่อไปจะเริ่มเขียนแนะนำส่วนประกอบทีละอย่าง
ส่วน widget ใจกลาง {.setCentralWidget}
การใช้ QMainWindow นั้นเริ่มจากตั้ง central widget ซึ่งเป็นตัว widget ที่เป็นส่วนประกอบหลักส่วนใจกลาง โดยใช้เมธอด .setCentralWidget
widget ใจกลางนั้นอาจใช้เป็น QWidget ธรรมดาแล้วก็ใส่องค์ประกอบอื่นลงไปใน widget นั้นเหมือนตอนที่ใช้ QWidget ธรรมดาเป็นหน้าต่าง
ตัวอย่าง ลองสร้าง QMainWindow ขึ้นมาแล้วตั้ง widget ใจกลาง แล้วใส่ช่องเขียนข้อความเข้าไปอีกที
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow,QWidget,QTextEdit
qAp = QApplication(sys.argv)
natang = QMainWindow()
natang.resize(300,200)
natang.setStyleSheet('font-family: Tahoma; font-size: 18px')
klang = QWidget()
natang.setCentralWidget(klang)
chongkhian = QTextEdit('ช่องเขียนข้อความ',klang)
chongkhian.setStyleSheet('background-color: #e0e9ce;')
chongkhian.setGeometry(20,20,260,160)
natang.show()
qAp.exec_()
ก็จะได้หน้าต่างออกมาเหมือนทุกทีที่ใช้แค่ QWidget
ซึ่งที่จริงแล้วถ้าหากจะใช้แค่นี้ก็ไม่ต่างอะไรกับทุกที ไม่จำเป็นต้องใช้ QMainWindow ก็ได้ ดังนั้นตัวอย่างนี้แค่ยกขึ้นมาให้เห็นว่าใช้ QMainWindow แทน QWidget ก็สร้างหน้าต่าง GUI ขึ้นมาใช้งานได้ในลักษณะเดียวกัน ส่วนตัวอย่างต่อไปจะเริ่มแนะนำส่วนประกอบเพิ่มเติมของ QMainWindow แต่ละอย่าง
ส่วนแถบสถานะด้านล่าง {.statusBar .showMessage}
แถบสถานะ (status bar) เป็นส่วนประกอบที่วางอยู่ด้านล่างสุดของหน้าต่าง มักใช้ขึ้นข้อความชั่วคราวเพื่อบอกสถานะอะไรบางอย่าง
การใส่แถบสถานะทำได้โดยใช้เมธอด .statusBar ที่ตัว QMainWindow จากนั้นจะได้คืนค่าเป็นออบเจ็กต์ QStatusBar ซึ่งแทนแถบสถานะที่ถูกสร้างขึ้นมาด้านล่างของหน้าต่างนี้
การแสดงข้อความในแถบสถานะทำได้โดยเมธอด โดยหากต้องการให้ข้อความปรากฏขึ้นแค่ชั่วคราวก็อาจใส่คีย์เวิร์ด msecs โดยกำหนดเวลาที่จะให้ข้อความปรากฏขึ้น หน่วยเป็นมิลลิวินาที
ตัวอย่าง ลองสร้างปุ่ม QPushButton ขึ้นมาเป็น widget ส่วนหลัก แล้วสร้างแถบสถานะขึ้น จากนั้นให้แสดงข้อความในแถบสถานะเมื่อกดปุ่ม แล้วจะหายหลังผ่านไป 1 วินาที
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow,QWidget,QPushButton
qAp = QApplication(sys.argv)
natang = QMainWindow()
natang.resize(290,180)
natang.setStyleSheet('font-family: Tahoma; font-size: 18px;')
klang = QWidget() # widget ใจกลาง
natang.setCentralWidget(klang)
pumkot = QPushButton('ปุ่มในส่วนกลาง',klang)
pumkot.setGeometry(15,15,260,100)
staba = natang.statusBar() # สร้างแถบสถานะ
# ให้แสดงข้อความเมื่อกดปุ่ม
def sadaengkhokhwam():
staba.showMessage('ข้อความในแถบข้อความด้านล่าง',msecs=1000)
pumkot.clicked.connect(sadaengkhokhwam)
staba.setFixedHeight(50) # ปรับความสูงของแถบสถานะ
natang.show()
qAp.exec_()
จะได้หน้าต่างที่มีปุ่มแบบนี้ ลองกดดูเพื่อให้แสดงข้อความที่แถบด้านล่างขึ้นมาได้
การสร้างแถบประกบ {.addDockWidget QDockWidget}
อีกส่วนประกอบหนึ่งที่สามารถสร้างขึ้นได้ใน QMainWindow ก็คือ QDockWidget ซึ่งเป็น widget ที่เหมือนเป็นแผ่นที่มาประกบเข้ากับ widget ส่วนกลางอีกที สามารถลากไปมาได้ หรือทำให้ลอยแยกเป็นอิสระได้
การใส่ QDockWidget ลงไปทำได้โดยใช้เมธอด .addDockWidget โดยให้กำหนดตำแหน่งเริ่มต้นที่จะให้ QDockWidget นั้นวางอยู่โดยใช้แฟล็ก เช่น Qt.LeftDockWidgetArea เพื่อวางทางซ้าย หรือ Qt.TopDockWidgetArea เพื่อวางด้านบน เป็นต้น
ตัวอย่างเช่น ลองสร้างหน้าต่างที่มีส่วนแถบประกบอยู่ ๒ อัน
import sys
from PyQt5.QtWidgets import QApplication,QLabel,QPushButton,QMainWindow,QDockWidget,QTextEdit,QScrollArea
from PyQt5.QtCore import Qt
qAp = QApplication(sys.argv)
natang = QMainWindow()
natang.setStyleSheet('font-family: Tahoma; font-size: 22px;')
natang.resize(400,270)
pumklang = QPushButton('ปุ่มกลาง') # widget ส่วนใจกลาง
natang.setCentralWidget(pumklang) # กำหนดให้ widget ใจกลางเป็นปุ่ม QPushButton
staba = natang.statusBar() # ใส่แถบสถานะที่ด้านล่างด้วย
staba.showMessage('แถบด้านล่าง')
dowi1 = QDockWidget('แถบประกบ 1',natang) # สร้าง QDockWidget ตัวแรก
chongkhian = QTextEdit('x_x') # ใส่กล่องแก้ข้อความลงไปใน QDockWidget ตัวนี้
dowi1.setWidget(chongkhian)
chongkhian.setStyleSheet('background-color: #d4a1c5;') # ใส่สีกล่องแก้ข้อความ
natang.addDockWidget(Qt.RightDockWidgetArea,dowi1) # ใส่ QDockWidget ลงไปใน QMainWindow โดยวางทางขวา
dowi2 = QDockWidget('แถบประกบ 2',natang) # สร้าง QDockWidget อีกตัว
phuenluean = QScrollArea() # ใส่พื้นที่เลื่อนได้ลงไปใน QDockWidget ตัวนี้
phuenluean.setStyleSheet('background-color: #a1d4bf; font-size: 70px;') # ใส่สีพื้นเลื่อน
dowi2.setWidget(phuenluean)
konyai = QLabel('/人◕ ‿‿ ◕人\') # ใส่ข้อความลงไปในพื้นเลื่อน
phuenluean.setWidget(konyai)
natang.addDockWidget(Qt.TopDockWidgetArea,dowi2) # ใส่ QDockWidget ลงไปใน QMainWindow โดยวางด้านบน
natang.show()
qAp.exec_()
ก็จะได้หน้าต่างที่แบ่งเป็น ๓ ส่วนแบบนี้ โดยส่วนด้านบนและด้านขวานั้นสามารถกดลากให้ลอยเป็นหน้าต่างแยกขึ้นมา หรือย้ายตำแหน่งไปประกบฝั่งอื่นแทนได้
แถบเมนู {.menuBar}
แถบเมนู (menu bar) คือส่วนแถบตัวเลือกที่วางอยู่ด้านบนเพื่อไว้ใส่ปุ่มอะไรต่างๆ
การสร้างแถบเมนูขึ้นมาทำได้โดยใช้เมธอด .menuBar จากนั้นจะคืนค่ามาเป็นตัวออบเจ็กต์แถบเมนู QMenuBar
สำหรับใน mac ต้องใช้เมธอด .setNativeMenuBar(False) ที่ตัวออบเจ็กต์แถบเมนูนี้ด้วย ไม่เช่นนั้นแถบเมนูจะไม่ขึ้น
ใช้เมธอด .addMenu เพื่อใส่หน้าเมนู จะคืนค่ามาเป็นออบเจ็กต์ QMenu จากนั้นให้สร้าง QAction ขึ้นมาแล้วใส่ตัวเลือกลงไปในหน้านั้นๆด้วยเมธอด .addAction
QAction แต่ละตัวที่ขึ้นมานี้ก็จะเป็นตัวเลือกสำหรับให้เมื่อกดแล้วมีการทำตามคำสั่งที่กำหนด โดยฟังก์ชันที่จะให้ทำเมื่อถูกกดเลือกนั้นให้ใส่ไปที่ .connect ของ .triggered
ตัวออบเจ็กต์ QAction นั้นสามารถใช้ .setStatusTip เพื่อตั้งข้อความที่จะให้ปรากฏอยู่ในแถบสถานะด้านล่างเมื่อเอาเมาส์ไปวางได้
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QLabel,QMainWindow,QAction
rakharuam = 0 # ค่าราคารวม
def buak(rakha): # ฟังก์ชันสำหรับบวกเพิ่มราคารวมตามค่าที่ใส่เข้าไป
global rakharuam
rakharuam += rakha
bokrakha.setText(str(rakharuam)+'บาท') # แสดงค่าราคา
qAp = QApplication(sys.argv)
natang = QMainWindow()
natang.setStyleSheet('font-family: Tahoma;')
bokrakha = QLabel('0 บาท') # ข้อความแสดงราคารวม
bokrakha.setStyleSheet('font-size: 20px;')
natang.setCentralWidget(bokrakha) # ให้ข้อความแสดงราคารวมเป็น widget ใจกลาง
thaepsathana = natang.statusBar() # สร้างแถบสถานะ
thaepmenu = natang.menuBar() # สร้างแถบเมนู
thaepmenu.setNativeMenuBar(False) # สำหรับ mac ต้องใส่เข้าไม่เช่นนั้นจะไม่แสดงแถบเมนู
namenu1 = thaepmenu.addMenu('อาหารไทย') # ใส่หน้าเมนูในแถบเมนู
ahan1 = QAction('ราดหน้า') # ใส่ตัวเลือกในหน้าเมนู
namenu1.addAction(ahan1)
ahan1.setStatusTip('89 บาท') # ข้อความที่ให้แสดงที่แถบสถานะเมื่อเอาเมาส์วาง
ahan1.triggered.connect(lambda :buak(89)) # ทำให้ฟังก์ชันทำงานเมื่อกดเลือกตัวเลือกในเมนู
ahan2 = QAction('ผัดไทย')
namenu1.addAction(ahan2)
ahan2.setStatusTip('99 บาท')
ahan2.triggered.connect(lambda :buak(99))
namenu2 = thaepmenu.addMenu('อาหารญี่ปุ่น')
ahan3 = QAction('ราเมง')
namenu2.addAction(ahan3)
ahan3.setStatusTip('100 บาท')
ahan3.triggered.connect(lambda :buak(100))
ahan4 = QAction('โซบะ')
namenu2.addAction(ahan4)
ahan4.setStatusTip('110 บาท')
ahan4.triggered.connect(lambda :buak(110))
natang.show()
qAp.exec_()
จะได้หน้าต่างแบบนี้ ลองกดที่แถบด้านบนก็จะมีตัวเลือกย่อยปรากฏขึ้นมา พอเอาเมาส์ไปวางบนนั้นก็จะปรากฏข้อความที่แถบสถานะด้านล่าง ถ้ากดเลือกก็จะบวกเพิ่มราคาที่แสดงอยู่ในส่วนหลักของหน้าต่าง
แถบเครื่องมือ {.toolBarArea}
แถบเครื่องมือ (toolbar) เป็นแถบประกบคล้ายกับ QDockWidget มักเอาไว้ใส่พวกปุ่มเครื่องมือต่างๆที่ใช้งานบ่อย ปกติมักจะอยู่ด้านบนของหน้าต่าง โดยถ้ามีแถบเมนูอยู่แล้วแถบเครื่องมือจะอยู่ใต้แถบเมนู นอกจากนี้สามารถคลิกลากเพื่อย้ายไปวางที่อื่นหรือเป็นหน้าต่างลอยขึ้นมาได้
ปุ่มภายในแถบเครื่องมือนั้นใช้ออบเจ็กต์ QAction เช่นเดียวกับแถบเมนู หลักการใช้งานก็คล้ายกัน
ตัวอย่างเช่น สร้างแถบเครื่องมือขึ้นมาแล้วใส่ปุ่มลงไปให้พอกดแล้วมีการบวกค่าตัวเลขที่แสดงในส่วนใจกลาง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QLabel,QMainWindow,QAction,QHBoxLayout
qAp = QApplication(sys.argv)
natang = QMainWindow()
natang.setStyleSheet('font-family: Courier New; font-size: 19px;')
thaepsathana = natang.statusBar()
cenwid = QWidget()
natang.setCentralWidget(cenwid)
hbl = QHBoxLayout()
cenwid.setLayout(hbl)
hbl.addWidget(QLabel('รวม '))
bokrakha = QLabel('0') # ตัวเลขแสดงตราคารวม
hbl.addWidget(bokrakha)
hbl.addWidget(QLabel('บาท'))
hbl.addStretch()
thaep_upakon = natang.addToolBar('') # สร้างแถบเครื่องมือ
upakon1 = QAction('เมาส์') # ใส่ตัวเลือก
thaep_upakon.addAction(upakon1)
upakon1.setStatusTip('+199 บาท') # ข้อความที่ให้แสดงที่แถบสถานะเมื่อเอาเมาส์วาง
upakon1.triggered.connect(lambda :bokrakha.setText(str(int(bokrakha.text())+199)))
upakon2 = QAction('คีย์บอร์ด')
upakon2.setStatusTip('+299 บาท')
thaep_upakon.addAction(upakon2)
upakon2.triggered.connect(lambda :bokrakha.setText(str(int(bokrakha.text())+299)))
upakon3 = QAction('ธัมบ์ไดรฟ์')
upakon3.setStatusTip('+499 บาท')
thaep_upakon.addAction(upakon3)
upakon3.triggered.connect(lambda :bokrakha.setText(str(int(bokrakha.text())+499)))
natang.show()
qAp.exec_()
นอกจากนี้ ปุ่มตัวเลือกสามารถใส่เป็นรูปไอคอนได้ด้วย ในตัวอย่างนี้ไม่ได้ใส่รูปไอคอนให้ปุ่ม ดังนั้นที่ปุ่มจึงขึ้นเป็นตัวหนังสือ แต่โดยทั่วไปเราจะเห็นว่าแถบเครื่องมือมักจะใช้ภาพไอคอนเป็นปุ่มมากกว่า
กรณีที่มีการใส่รูปไอคอน ที่ปุ่มจะแสดงเป็นรูปไอคอนแทนตัวหนังสือ หากใส่ตั้งไอคอนทั้งตัวหนังสือ แบบนี้ตัวหนังสือจะปรากฏขึ้นแค่เมื่อเอาเมาส์ไปวางที่ปุ่ม
ตัวอย่างเช่น ถ้าจะลองสร้างแถบเครื่องมือโดยใช้รูปนี้เป็นไอคอนในปุ่ม
ก็เขียนได้ดังนี้
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow,QAction
from PyQt5.QtGui import QIcon
qAp = QApplication(sys.argv)
natang = QMainWindow()
thaep_upakon = natang.addToolBar('แถบเครื่องมือ')
upakon_qb = QAction(QIcon('qbicon.png'),'qb')
thaep_upakon.addAction(upakon_qb)
natang.show()
qAp.exec_()
จะได้หน้าต่างที่มีแถบข้อมูลที่มีรูปนี้เป็นไอคอนของปุ่มตัวเลือกอยู่ ถ้าเอาเมาส์ไปวางก็จะแสดงข้อความขึ้นมา
สรุปท้ายบท
ในบทนี้ได้แนะนำให้รู้จัก QMainWindow และส่วนประกอบต่างๆไปแบบคร่าวๆในภาพรวมไปแล้ว แต่ว่าแต่ละส่วนนั้นยังมีรายละเอียดการใช้งานอีกมากซึ่งไม่ได้เขียนถึงในนี้ สามารถศึกษาเพิ่มเติมต่อได้
อ่านบทถัดไป >>
บทที่ ๒๑