ต่อจาก
บทที่ ๒๐
ในบทนี้จะเป็นเรื่องของการใช้ QListWidget ซึ่งเป็นช่องที่ไว้ใส่ข้อความเรียงกันไปเป็นแถวจากบนลงล่าง มีส่วนคล้ายกับ
QComboBox
ที่เขียนถึงไปแล้วใน
บทที่ ๑๒
แต่มักใช้เพื่อเก็บใส่และไล่เรียงข้อความ มากกว่าที่จะใช้เพื่อเลือก
การสร้างพื้นที่แสดงกลุ่มข้อความและการใส่ข้อความลงในกลุ่ม {QListWidget .addItem .addItems
.insertItem .insertItems}
การสร้างและใช้งาน QListWidget นั้นคล้ายกับ QComboBox โดยเริ่มจากสร้างออบเจ็กต์ QListWidget
ขึ้นมาแล้วค่อยๆเติมข้อความเข้าไปทีละตัวโดยใช้เมธอด .addItem หรือใช้ .addItems เพื่อใส่ทีละหลายตัว หรืออาจใช้
.insertItem หรือ .insertItems เพื่อแทรกลงไปในตำแหน่งที่ต้องการ
ตัวอย่างการสร้างและใส่ข้อความลงในพื้นที่แสดงกลุ่มข้อความ
import sys
from PyQt5.QtWidgets import QApplication,QListWidget,QWidget
qAp = QApplication(sys.argv)
natang = QWidget()
raikan = QListWidget(natang) # สร้างพื้นที่แสดงกลุ่มข้อความ
css = '''font-size: 18px;
font-family: Courier New;
background-color: #159;
color: #6df;
selection-background-color: #47b;
selection-color: #fac;'''
raikan.setStyleSheet(css)
raikan.setGeometry(10,10,150,160)
raikan.addItem('ฟุชิงิดาเนะ') # ใส่อันเดียว
raikan.addItems(['ลิซาร์โด','ลิซาร์ดอน']) # ใส่หลายอัน
raikan.insertItems(1,['ฟุชิงิโซว','ฟุชิงิบานะ']) # แทรกอันเดียว
raikan.insertItem(3,'ฮิโตคาเงะ') # แทรกหลายอัน
natang.show()
qAp.exec_()
อนึ่ง selection-background-color ที่ตั้งไว้ภายใน .setStyleSheet
นั้นในที่นี้ใช้ปรับสีพื้นหลังของข้อความที่ถูกกดเลือกอยู่ ส่วน selection-color ใช้ปรับสีข้อความที่ถูกเลือก
ถ้าขนาดเกินไปจากที่กำหนดไว้ พื้นที่แสดงกลุ่มข้อความนั้นจะกลายเป็นพื้นที่เลื่อนที่มีแถบเลื่อน
ออบเจ็กต์รายการตัวเลือก {.item .row QListWidgetItem}
ที่จริงแล้วเมื่อมีการเพิ่มข้อความลงไปใน QListWidget นั้นจะเป็นการสร้างออบเจ็กต์ QListWidgetItem
ซึ่งบรรจุข้อความนั้นขึ้นมาโดยอัตโนมัติ
หากใช้เมธอด .item ที่ตัวออบเจ็กต์ QListWidget ก็จะได้ออบเจ็กต์ QListWidgetItem ตามตำแหน่งลำดับแถวที่ระบุ (เริ่มจาก
0)
ถ้าต้องการเอาข้อความจากออบเจ็กต์นั้นให้ใช้เมธอด .text นอกจากนี้หากเรียกเมธอด .row ที่ตัว QListWidget โดยใส่ตัว
QListWidgetItem ลงไปก็จะได้ลำดับแถวของตัว QListWidgetItem นั้น
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QListWidget
qAp = QApplication(sys.argv)
raikan = QListWidget()
raikan.setStyleSheet('font-size: 21px; font-family: Tahoma; background-color: #fee; color: #f86;')
raikan.addItems(['เซนิงาเมะ','คาเมล','คาเม็กซ์','โป๊ปโป','พีเจียน','พีจ็อต'])
item = raikan.item(2) # เอาตัวออบเจ็กต์ QListWidgetItem นั้นออกมาดู
print(item) # ได้ <PyQt5.QtWidgets.QListWidgetItem object at 0x7fcd620e5f70>
print(item.text()) # ได้ คาเม็กซ์
print(raikan.row(item)) # ได้ 2
print(raikan.item(0).text()) # ได้ เซนิงาเมะ
# เอาตัวลำดับที่ 2 จากท้าย
print((raikan.item(raikan.count()-2)).text()) # ได้ พีเจียน
raikan.show()
qAp.exec_()
ในที่นี้เมธอด .count ใช้นับจำนวนข้อความที่ใส่อยู่ในนั้น
เมื่อใช้เมธอด .addItem เพื่อเพิ่มข้อความเข้าไปนั้นจริงๆจะใส่ตัวออบเจ็กต์ QListWidgetItem ลงไปก็ได้ เช่น
import sys
from PyQt5.QtWidgets import QApplication,QListWidget,QListWidgetItem
qAp = QApplication(sys.argv)
raikan = QListWidget()
raikan.setStyleSheet('font-family: Tahoma; font-size: 40px;')
raikan.addItem(QListWidgetItem('โครัตตา'))
raikan.addItem(QListWidgetItem('รัตตา'))
raikan.show()
qAp.exec_()
เพียงแต่ว่าปกติแค่ใส่ข้อความลงไป ตัว QListWidgetItem
ของข้อความนั้นก็จะถูกสร้างขึ้นโดยอัตโนมัติอยู่แล้วเลยอาจไม่จำเป็นต้องเขียนแบบนี้
การเลือกแถว {.setCurrentRow .setCurrentItem}
เมธอด .setCurrentRow ใช้เพื่อปรับให้แถวที่กดเลือกอยู่ใน QListWidget เปลี่ยนไปเป็นแถวที่ต้องการได้
เหมือนกับเวลาที่เราไปกดคลิกด้วยเมาส์ ดังนั้นอาจใช้เพื่อควบคุมตัวเลือกภายใน QListWidget แบบทางอ้อมจากที่อื่น
ตัวอย่างเช่น ลองใช้ .setEnabled(False) ทำให้ QListWidget นั้นไม่สามารถกดเลือกได้เอง แต่สร้าง QSlider
ขึ้นมาให้เลือกตัวเลือกใน
QListWidget นั้นตามตำแหน่งที่ QSlider เลื่อนไปก็ได้
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QListWidget,QVBoxLayout,QSlider
from PyQt5.QtCore import Qt
qAp = QApplication(sys.argv)
natang = QWidget()
vbl = QVBoxLayout()
natang.setLayout(vbl)
raikan = QListWidget()
vbl.addWidget(raikan)
raikan.setStyleSheet('font-size: 18px; font-family: Tahoma; background-color: #afb;')
raikan.addItems(['อาร์โบ','อาร์บ็อก','พิคาชู','ไรชู'])
raikan.setEnabled(False) # ตั้งให้กดเลือกในนี้เองไม่ได้
raikan.setCurrentRow(0)
tualuean = QSlider() # สร้างตัวลูกเลื่อนที่จะใช้เลื่อนปรับค่าเพื่อแทนการกดเลือก
vbl.addWidget(tualuean)
tualuean.setOrientation(Qt.Horizontal) # ทำให้เป็นแนวนอน
tualuean.setRange(0,3)
def luean(): # เมื่อเลื่อนตัวเลื่อน
kha = tualuean.value()
raikan.setCurrentRow(kha) # ตัวเลือกในกลุ่มข้อความนั้นก็ปรับตาม
tualuean.valueChanged.connect(luean)
tualuean.setValue(2) # ให้เริ่มต้นมาก็เลือกตัวที่ตำแหน่ง 2 เลย
natang.show()
qAp.exec_()
ถ้ากดเลื่อนที่ตัวลูกเลื่อน ตัวเลือกใน QListWidget จึงจะเปลี่ยนตาม
นอกจากนี้ยังมีเมธอด .setCurrentItem ซึ่งก็ใช้กำหนดตัวที่จะเลือก เช่นเดียวกับ .setCurrentRow
เพียงแต่ค่าที่ต้องใส่คือตัวออบเจ็กต์ QListWidgetItem ที่จะเลือก
การดูว่าเลือกแถวไหนอยู่ {.currentRow .currentItem}
หากจะเอาข้อมูลว่าตอนนี้แถวลำดับไหนถูกเลือกอยู่อาจใช้เมธอด .currentRow หรือถ้าต้องการได้เป็นตัวออบเจ็กต์
QListWidgetItem ของแถวนั้นก็ให้ใช้
.currentItem
แต่ถ้าหาก QListWidget นั้นอยู่ในสถานะที่ยังไม่ได้เลือกแถวไหนเลย แบบนั้นเมื่อใช้ .currentRow จะได้ -1 ส่วน .currentItem
จะได้ None
ตัวอย่างการใช้
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QListWidget,QVBoxLayout,QSlider
from PyQt5.QtCore import Qt
qAp = QApplication(sys.argv)
natang = QWidget()
vbl = QVBoxLayout()
natang.setLayout(vbl)
natang.setStyleSheet('font-size: 25px; font-family: Courier New; selection-background-color: #173;')
raikan = QListWidget()
vbl.addWidget(raikan)
raikan.addItems(['บีเดิล','โคคูน','สเปียร์'])
print(raikan.currentRow()) # ได้ -1
print(raikan.currentItem()) # ได้ None
raikan.setCurrentRow(0)
print(raikan.currentRow()) # ได้ 0
print(raikan.currentItem()) # ได้ <PyQt5.QtWidgets.QListWidgetItem object at 0x7f82b279e430>
print(raikan.currentItem().text()) # ได้ บีเดิล
natang.show()
qAp.exec_()
การทำคำสั่งเมื่อแถวที่เลือกถูกเปลี่ยน {.currentRowChanged .currentTextChanged
.currentItemChanged}
หากมีคำสั่งที่ต้องการจะให้ทำเมื่อมีการเปลี่ยนแถวที่เลือกก็อาจตั้ง .connect ที่ .currentRowChanged หรือ
.currentTextChanged
โดยความแตกต่างก็คือพารามิเตอร์ที่ได้ โดย .currentRowChanged จะได้เลขลำดับของแถวที่เลือก ส่วน
.currentTextChanged จะได้ข้อความในแถวที่เลือก ส่วน .currentItemChanged จะได้ตัวออบเจ็กต์ QListWidgetItem
ของแถวที่เลือก
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QLabel,QListWidget,QHBoxLayout,QVBoxLayout
qAp = QApplication(sys.argv)
natang = QWidget()
hbl = QHBoxLayout()
natang.setLayout(hbl)
natang.setStyleSheet('font-size: 18px; font-family: Courier New;')
raikan = QListWidget()
raikan.addItems(['ปิปปี','ปิกซี','โรคอน','คิวคอน'])
def kaelek(lek): # แสดงลำดับที่เลือก
leklueak.setText('~%d~'%lek)
def kaekhokhwam(text): # แสดงข้อความที่เลือก
khalueak.setText(text)
raikan.currentRowChanged.connect(kaelek)
raikan.currentTextChanged.connect(kaekhokhwam)
hbl.addWidget(raikan)
vbl = QVBoxLayout()
hbl.addLayout(vbl)
leklueak = QLabel('')
vbl.addWidget(leklueak)
khalueak = QLabel('')
vbl.addWidget(khalueak)
raikan.setCurrentRow(2)
natang.show()
qAp.exec_()
จะได้กล่องข้อความแบบนี้ ซึ่งพอลองเปลี่ยนตัวเลือกดู ข้อความและตัวเลขทางขวาก็เปลี่ยนไปด้วย
นอกจากนี้ยังอาจใช้ .currentItemChanged ซึ่งจะทำงานตอนที่เปลี่ยนตัวเลือกเช่นเดียวกับ .currentRowChanged หรือ
.currentTextChanged โดยจะได้พารามิเตอร์เป็ฯตัวออบเจ็กต์ QListWidgetItem
แต่จะได้มาทั้งตัวเลือกก่อนเปลี่ยนและหลังเปลี่ยน
ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QLabel,QListWidget,QHBoxLayout
qAp = QApplication(sys.argv)
natang = QWidget()
natang.setStyleSheet('font-family: Tahoma; font-size: 18px; color: #732;')
hbl = QHBoxLayout()
raikan = QListWidget()
hbl.addWidget(raikan)
natang.setLayout(hbl)
raikan.setStyleSheet('font-size: 20px; background-color: #def;')
raikan.addItems(['เนียร์ธ','เพอร์เซียน','โคดัก','โกลดัก'])
khalueak = QLabel('')
def kaekhokhwam(b,a): # ในที่นี้ b และ a คือออบเจ็กต์ตัวเลือกหลังและก่อนเปลี่ยน
if(a): # ถ้ามีตัวที่เลือกอยู่ก่อนหน้าจึงให้เขียน
khalueak.setText(a.text()+' > '+b.text())
raikan.currentItemChanged.connect(kaekhokhwam)
raikan.setCurrentRow(1)
raikan.setCurrentRow(2)
hbl.addWidget(khalueak)
natang.show()
qAp.exec_()
การคำทำสั่งเมื่อตัวเลือกถูกเมาส์คลิก {.itemPressed .itemClicked
.itemDoubleClicked}
ถ้ามีคำสั่งที่ต้องการให้ทำเมื่อมีการคลิกเมาส์สามารถตั้ง .connect ที่ .itemPressed หรือ .itemClicked โดย .itemPressed
จะทำงานตอนที่เมาส์ถูกกด แต่ .itemClicked จะทำงานเมื่อเมาส์ถูกกดแล้วปล่อย
ส่วน .itemDoubleClicked จะทำงานเมื่อถูกดับเบิลคลิก
ตัวอย่าง เช่นลองทำให้เมื่อถูกคลิกแล้วมีข้อความปรากฏที่แถบสถานะด้านล่าง ถ้าดับเบิลคลิกจะปรากฏกล่องเด้งแสดงข้อความ
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow,QListWidget,QMessageBox
qAp = QApplication(sys.argv)
natang = QMainWindow()
thaepsathana = natang.statusBar()
natang.setStyleSheet('*{font-family: Courier New;} QListWidget{font-size: 21px; margin: 10px;}')
def thukkot(item):
print(item.text()+' ถูกกด')
def thukclick(item):
thaepsathana.showMessage(item.text()+' ถูกกดแล้วปล่อย')
def thukdoubleclick(item):
QMessageBox.warning(natang,'',item.text()+' ถูกดับเบิลคลิก')
raikan = QListWidget()
natang.setCentralWidget(raikan)
raikan.addItems(['อีวุย','เชาเวอร์ส','ธันเดอร์ส','บูสเตอร์'])
raikan.itemPressed.connect(thukkot)
raikan.itemClicked.connect(thukclick)
raikan.itemDoubleClicked.connect(thukdoubleclick)
natang.show()
qAp.exec_()
อ่านบทถัดไป >>
บทที่ ๒๒