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



pyqt เบื้องต้น บทที่ ๒: การสร้างปุ่มและจัดขนาดและตำแหน่งของ widget
เขียนเมื่อ 2021/08/04 11:51
แก้ไขล่าสุด 2021/09/28 16:42

ต่อจาก บทที่ ๑

หลังจากที่ในบทที่แล้วได้แนะนำให้รู้จักภาพรวมการใช้งาน และความหมายของ widget แล้ว ในบทนี้จะเป็นเรื่องของการจัดการกับ widget ซึ่งรวมถึง widget หลักที่ใช้เป็นหน้าต่าง และ widget ที่ถูกใส่เป็นส่วนประกอบข้างใน โดยจะใช้ปุ่มกด QPushButton เป็นตัวอย่าง




การใส่ปุ่มกด {QPushButton}

พูดถึง GUI แล้ว สิ่งที่น่าจะเจอบ่อยที่สุดก็คงจะเป็นปุ่มกด ใน qt นั้นปุ่มกดสร้างได้โดยคลาส QPushButton

การใส่ปุ่มกดลงในหน้าต่างทำได้โดยสร้างอินสแตนซ์ของคลาส QPushButton โดยใส่อาร์กิวเมนต์เป็นตัว widget หลัก ที่ต้องการเอาปุ่มไปใส่
QPushButton(widget_หลัก)

แต่ถ้าหากต้องการให้มีข้อความบนปุ่มด้วยก็ให้ใส่ข้อความก่อน แล้วจึงตามด้วย widget หลัก
QPushButton(ข้อความ,widget_หลัก)

ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton

qAp = QApplication(sys.argv)
natang = QWidget()
pumkot = QPushButton('กด กด',natang)
natang.show()
qAp.exec_()

จากนั้นก็จะได้ปุ่มออกมาอยู่ภายในหน้าต่าง ซึ่งลักษณะก็แตกต่างกันไปขึ้นอยู่กับระบบปฏิบัติการที่ใช้

ใน windows10



ใน mac



ใน linux



ดูแล้วใน mac จะสวยที่สุดไม่ว่าจะเป็นตัวหน้าต่างหรือปุ่มกด ดังนั้นในตัวอย่างต่อจากนี้ไปจะแสดงผลการรันใน mac เป็นหลัก

ปุ่มที่ได้ออกมานี้สามารถลองกดดูได้ เพียงแต่ตอนนี้ถึงกดไปก็ไม่มีอะไรเกิดขึ้น เพราะเราแค่สร้างปุ่มขึ้นมาเฉยๆ ยังไม่ได้กำหนดหน้าที่การทำงานให้มัน

เรื่องของการให้ปุ่มทำงานได้นั้นจะเขียนถึงในบทที่ ๔




การตั้งรูปให้ปุ่ม {QIcon}

นอกจากจะใส่ข้อความลงบนปุ่มแล้ว ยังสามารถใส่รูปลงบนปุ่มได้ด้วย โดยหากต้องการใส่รูป เวลาที่สร้างปุ่มให้เพิ่มอาร์กิวเมนต์อีกตัว นำหน้าข้อความ
QPushButton(รูป,ข้อความ,widget_หลัก)

โดยรูปที่ใส่นั้นต้องเป็นออบเจ็กต์ของคลาส QIcon ซึ่งเรียกใช้จากมอดูล PyQt5.QtGui

ในที่นี้ขอใช้ภาพนี้เป็นตัวอย่าง

qbicon.png


ตัวอย่างการใช้
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton
from PyQt5.QtGui import QIcon

qAp = QApplication(sys.argv)
natang = QWidget()
pumkot = QPushButton(QIcon('qbicon.png'),'qb',natang)
natang.show()
qAp.exec_()

แล้วก็จะได้ออกมาเป็นแบบนี้ มีทั้งภาพและตัวหนังสืออยู่บนปุ่ม






การกำหนดตำแหน่งและขนาดของ widget หรือหน้าต่าง {.setGeometry}

ในตัวอย่างที่ผ่านมาเราแค่สั่งให้สร้างหน้าต่างกับปุ่มขึ้นมาโดยไม่ได้กำหนดว่าให้มันวางตรงไหนหรือมีขนาดเท่าไหร่ ดังนั้นขนาดกับตำแหน่งก็จะถูกกำหนดเองตามความเหมาะสม โดยอาจขึ้นกับสภาวะแวดล้อมหรือค่าตั้งต้นในนั้น

โดยทั่วไปแล้วเราควรจะกำหนดตำแหน่งหรือขนาดของ widget ให้ ซึ่งก็มีอยู่หลายวิธี แต่วิธีที่เข้าใจง่ายที่สุดก็คือการกำหนดค่าตำแหน่งและขนาดโดยตรง โดยใช้เมธอด .setGeometry

วิธีการใช้
ตัว_widget.setGeometry(ระยะห่างจากขอบบน,ระยะห่างจากขอบซ้าย,ขนาดแนวนอน,ขนาดแนวตั้ง)

ตัวอย่าง ลองใช้เพื่อปรับขนาดและตำแหน่งหน้าต่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget

qAp = QApplication(sys.argv)
natang = QWidget()
natang.setGeometry(200,200,160,80)
natang.show()
qAp.exec_()

ก็จะได้หน้าต่างขนาด 160×80 แบบนี้ออกมา ส่วนตำแหน่งก็จะอยู่ที่ 200,200 จากมุมซ้ายบนของหน้าจอ





เมธอดนี้ใช้ได้กับ widget ทั้งหมด ซึ่งส่วนประกอบต่างๆภายในหน้าต่างเช่น QPushButton เองก็เป็น widget เช่นกัน จึงสามารถจัดวางได้ด้วยวิธีเดียวกันนี้

ในกรณีที่ใช้กับ widget ที่เป็นส่วนประกอบด้านใน ตำแหน่งในที่นี้จะเป็นตำแหน่งจากมุมบนซ้ายของ widget หลัก

ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton

qAp = QApplication(sys.argv)
natang = QWidget()
natang.setGeometry(200,200,250,120)
pumkot = QPushButton('กฎหมายกดปรากฏ',natang)
pumkot.setGeometry(20,10,210,100)
natang.show()
qAp.exec_()

จะได้ปุ่มขนาด 210×100 ที่มีมุมซ้ายบนอยู่ที่ตำแหน่ง 20,10 จากขอบซ้ายบนของหน้าต่าง






กรณีที่ลองทำเป็นคลาส

ในบทที่แล้วก็ได้มีพูดถึงไปเล็กน้อยว่าในกรณีทั่วไปการใช้ pyqt นั้นมักจะเขียนในรูปแบบเป็นคลาส

ในบทเรียนนี้เพื่อความง่ายจะเน้นเขียนแบบไม่ทำเป็นคลาสเป็นหลัก แต่ก็จะขอยกวิธีการเขียนในแบบที่ทำเป็นคลาสมาเทียบไปด้วย

ตัวอย่างที่แล้ว หากเขียนเป็นแบบทำเป็นคลาสก็จะเขียนได้แบบนี้
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton

class Natang(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(200,200,250,120)
        pumkot = QPushButton('กฎหมายกดปรากฏ',self)
        pumkot.setGeometry(20,10,210,100)
        self.show()

qAp = QApplication(sys.argv)
natang = Natang()
qAp.exec_()

ผลที่ได้ก็จะออกมาเหมือนเดิม (เลื่อนขึ้นไปดูภาพข้างบนเอา)

จะเห็นว่าเมื่อทำเป็นคลาส ส่วนที่กำหนดขนาดของหน้าต่างและการสร้างและกำหนดขนาดปุ่มจะทำภายใน __init__ ของคลาส แต่เนื้อหาก็เขียนเหมือนกับ เพียงแต่เมื่ออยู่ในคลาส ออบเจ็กต์ตังหน้าต่างจะแทนด้วย self เพราะตัวคลาสที่กำลังสร้างอยู่นี้คือตัวหน้าต่างนั้นเอง




การจัดวางตำแหน่ง widget {.move}

เมธอด .setGeometry นั้นจะเป็นการปรับทั้งขนาดและตำแหน่งของ widget ไปพร้อมกัน แต่ถ้าหากต้องการกำหนดแค่ตำแหน่งก็อาจใช้เมธอด .move แทน

วิธีการใช้ก็คล้ายกับ .setGeometry แค่ใส่แต่ค่าตำแหน่ง
ตัว_widget.move(ระยะห่างจากขอบบน,ระยะห่างจากขอบซ้าย)

ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton

qAp = QApplication(sys.argv)
natang = QWidget()
natang.move(120,120)
pumkot = QPushButton('กด กฎ',natang)
pumkot.move(50,20)
natang.show()
qAp.exec_()

จะได้ปุ่มอยู่ที่ตำแหน่ง 50,20 จากมุมซ้ายบนของหน้าต่าง ส่วนขนาดของปุ่มไม่ได้กำหนดไว้ จึงถูกกำหนดให้เองออกมาเป็นค่าตั้งต้นตามความเหมาะสม






การกำหนดขนาด widget {.resize}

เช่นเดียวกับที่ตำแหน่งกำหนดโดย .move หากต้องการกำหนดขนาดของ widget ทำได้โดยใช้ .resize ซึ่งผลจะเหมือนกับ setGeometry เพียงแต่จะไไม่มีการย้ายตำแหน่ง

วิธีใช้
ตัว_widget.resize(ขนาดแนวนอน,ขนาดแนวตั้ง)

ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton

qAp = QApplication(sys.argv)
natang = QWidget()
natang.resize(300,200)
pumkot1 = QPushButton('กดโกรธ',natang)
pumkot1.resize(210,160)
pumkot2 = QPushButton('กดชอบ',natang)
pumkot2.resize(130,70)
natang.show()
qAp.exec_()

ในที่นี้กำหนดแต่ขนาดแต่ว่าไม่ได้กำหนดตำแหน่ง แบบนี้ปุ่มก็จะอยู่ที่มุมซ้ายบน ส่วนหน้าต่างจะปรากฏขึ้นมากลางหน้าจอ






การกำหนดขนาด widget ตายตัว {.setFixedSize .setFixedWidth .setFixedHeight}

ปกติแล้วหน้าต่างที่สร้างขึ้นมานั้นจะสามารถปรับขนาดได้ แต่หากต้องการให้มีขนาดแน่นอนก็อาจทำได้โดยกำหนดขนาดด้วยเมธอด .setFixedSize หรือถ้าจะกำหนดแค่แนวนอนหรือแนวตั้งก็ใช้ .setFixedWidth กับ .setFixedHeight

วิธีการใช้ก็เหมือนกับ .resize เพียงแต่กรณีที่ใช้กับ widget ตัวหน้าต่างนั้นหน้าต่างที่ได้จะปรับขนาดไม่ได้ ส่วนถ้าใช้กับส่วนประกอบภายในที่แต่ไหนแต่ไรก็ปรับขนาดไม่ได้อยู่แล้วก็มีผลไม่ต่างจากการใช้ .resize คือแค่ทำการปรับขนาดไปเป็นขนาดที่กำหนด

ตัวอย่าง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton

qAp = QApplication(sys.argv)
natang = QWidget()
natang.setFixedSize(250,220)
pumkot1 = QPushButton('กดหมด',natang)
pumkot1.setFixedWidth(240)
pumkot1.setFixedHeight(210)
pumkot2 = QPushButton('กดบน',natang)
pumkot2.setFixedSize(170,100)
natang.show()
qAp.exec_()

ในกรณีที่ใช้ mac จะเห็นว่าหน้าต่างที่ได้ไม่มีปุ่มสีเขียวซึ่งใช้สำหรับขยายเต็มจอ เหลือแค่ปุ่มปิด (สีแดง) กับปุ่มย่อหน้าต่าง (สีเหลือง) นั่นเพราะหน้าต่างที่ได้นี้ปรับขนาดไม่ได้ ถ้าลองเอาเมาส์ไปวางที่ขอบก็จะไม่มีอะไรเกิดขึ้น






การกำหนดขอบเขตขนาดย่อขยายหน้าต่าง {.setMinimumSize .setMaximumSize}

หากต้องการให้หน้าต่างมีขนาดอยู่ในขอบเขตที่กำหนดก็อาจทำได้โดยใช้ .setMinimumSize เพื่อกำหนดขนาดเล็กสุดและใช้ .setMaximumSize เพื่อกำหนดขนาดใหญ่สุด

และในทำนองเดียวกันถ้าต้องการกำหนดแค่แนวนอนหรือแนวตั้งก็มี .setMinimumWidth .setMaxmumWidth .setMinimumHeight .setMaximumHeight ซึ่งวิธีใช้ก็เช่นเดียวกัน

ตัวอย่างการใช้ .setMinimumSize กับ .setMaximumSize
import sys
from PyQt5.QtWidgets import QApplication,QWidget

qAp = QApplication(sys.argv)
natang = QWidget()
natang.setMinimumSize(200,100)
natang.setMaximumSize(333,222)
natang.show()
qAp.exec_()

ผลที่ได้จะออกมาเป็นหน้าต่างที่มีขนาดเท่ากับที่กำหนดใน .setMaximumSize คือ 333×222 แต่สามารถปรับย่อลงได้ จนเหลือขนาดเล็กสุดตามที่กำหนดใน .setMinimumSize






สรุปท้ายบท

ในบทนี้ได้พูดถึงเรื่องการปรับแต่งจัดวาง widget เป็นหลัก โดยได้ถือโอกาสแสดงวิธีการสร้าง widget ที่สำคัญตัวหนึ่งคือปุ่มกด QPushButton ไปด้วยเพื่อใช้เป็นตัวอย่าง

เมธอดที่ใช้ปรับแต่ง widget เหล่านี้สามารถใช้กับ widget ชนิดอื่นๆที่จะเขียนถึงในบทต่อๆไปหลังจากนี้ได้เช่นกัน

สำหรับเรื่องการวางตำแหน่งของ widget นั้นในที่นี้ใช้ .setGeometry หรือ .move แต่นอกจากนี้แล้วก็ยังมีวิธีการจัดวางเป็นโครง layout แบบต่างๆ เช่น QHBoxLayout, QVBoxLayout, QGridLayout ซึ่งก็จะกล่าวถึงต่อไป



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





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

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

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

หมวดหมู่

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

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

สารบัญ

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

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

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



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

  ค้นหาบทความ

  บทความแนะนำ

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

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文