φυβλαςのβλογ
บล็อกของ phyblas



pyqt เบื้องต้น บทที่ ๒๑: การสร้างและใช้งานพื้นที่แสดงกลุ่มข้อความ
เขียนเมื่อ 2021/08/23 06:59
แก้ไขล่าสุด 2021/09/28 16:42

ต่อจาก บทที่ ๒๐

ในบทนี้จะเป็นเรื่องของการใช้ 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_()






อ่านบทถัดไป >> บทที่ ๒๒





-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> pyqt

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

ไทย

日本語

中文