φυβλαςのβλογ
phyblasのブログ



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

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

ในบทนี้จะพูดถึงเรื่องการสร้างพื้นที่ซึ่งสามารถเลื่อนไปมาเพื่อดูส่วนต่างๆได้ ซึ่งมีประโยชน์เวลาที่มีพื้นที่อยู่จำกัด ทำให้สามารถวางของที่ใหญ่กว่าพื้นที่ที่มีอยู่ได้




การสร้างพื้นที่เลื่อนได้ {QScrollArea}

พื้นที่เลื่อนได้สร้างได้โดยสร้างออบเจ็กต์ QScrollArea ขึ้นมา แล้วก็ใส่ widget ที่ต้องการให้เลื่อนได้ลงไปในนั้นโดยใช้เมธอด .setWidget

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

qAp = QApplication(sys.argv)
natang = QWidget()

phuenluean = QScrollArea(natang)
phuenluean.setGeometry(10,10,120,80)
khokhwam = QLabel('พื้นที่เลื่อนได้')
phuenluean.setStyleSheet('background-color: #ebe0ff; font-size: 45px; font-family: Tahoma')
phuenluean.setWidget(khokhwam)

natang.show()
qAp.exec_()

จะได้พื้นที่ศึ่งมีแถบเลื่อนติดอยู่แล้วสามารถเลื่อนได้แบบนี้ ในที่นี้มีแต่ในแนวนอน ไม่มีในแนวตั้ง เพราะว่าในแนวตั้งมีความสูงพออยู่แล้ว แต่ถ้าสูงไม่พอก็จะมีแถบเลื่อนในแนวตั้งด้วย






การใส่กรอบ {.setFrameShape}

ที่จริงแล้ว QSCrollArea นั้นเป็นซับคลาสของ QFrame (รายละเอียดอ่านในบทที่ ๖) ดังนั้นจึงสร้างกรอบล้อมได้ โดยหากสร้างกรอบขึ้นมา เงาที่ขอบจะเป็นแบบ Sunken คือเหมือนเป็นพื้นที่จมลงไป ถ้าจะให้เป็นกรอบธรรมดาไม่มีเงาก็ตั้ง .setFrameShadow เป็น Plain ได้
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QLabel,QFrame,QScrollArea

qAp = QApplication(sys.argv)
natang = QWidget()

phuenluean = QScrollArea(natang)
phuenluean.setGeometry(10,10,110,140)
xxyyzz = QLabel('xxxxx\nyyyyy\nzzzz')
phuenluean.setStyleSheet('background-color: #ffe0f4; font-size: 55px')
phuenluean.setLineWidth(5) # ตั้งความหนาของขอบ
phuenluean.setFrameShape(QFrame.Panel) # ตั้งรูปแบบขอบ
#phuenluean.setFrameShadow(QFrame.Plain) # เอาเงาขอบออก ถ้าไม่ต้องการให้เป็นพื้นจม
phuenluean.setWidget(xxyyzz)

natang.show()
qAp.exec_()

ก็จะได้พื้นที่เลื่อนที่มีกรอบดูแล้วเหมือนจมลงไปแบบนี้






การตั้งว่าจะให้มีแถบเลื่อนหรือไม่ในกรณีต่างๆ {.setHorizontalScrollBarPolicy .setVerticalScrollBarPolicy}

ปกติแล้วพื้นที่ใน QScrollArea จะมีแถบเลื่อนปรากฏขึ้นมาโดยอัตโนมัติเมื่อ widget ที่ใส่ในนั้นมีขนาดใหญ่เกินกว่าขนาดของ QScrollArea ที่ตั้งไว้

แต่หากต้องการให้แนวนอนหรือแนวตั้งมีแถบเลื่อนอยู่เสมอไม่ว่าจะพื้นที่เกินหรือเปล่าก็ทำได้โดยใช้ .setHorizontalScrollBarPolicy สำหรับแนวนอน และ .setVerticalScrollBarPolicy สำหรับแนวตั้ง โดยให้ใส่แฟล็ก Qt.ScrollBarAlwaysOn ลงไป

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

qAp = QApplication(sys.argv)
natang = QWidget()

phuenluean = QScrollArea(natang)
phuenluean.setGeometry(10,10,150,110)
phuenluean.setStyleSheet('background-color: #ffcece')

phuenluean.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
phuenluean.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)

natang.show()
qAp.exec_()

จะได้พื้นที่เลื่อนที่มีลูกศรทั้งแนวตั้งและแนวนอน แม้ว่าจะเลื่อนไม่ได้ก็ตาม



ในทางกลับกัน ถ้าจะให้ไม่มีแถบเลื่อนแม้ว่าขนาด widget ภายในใหญ่เกินก็ทำได้โดยตั้งแฟล็ก Qt.ScrollBarAlwaysOff

ตัวอย่างเช่น
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QLabel,QFrame,QScrollArea
from PyQt5.QtCore import Qt

qAp = QApplication(sys.argv)
natang = QWidget()

phuenluean = QScrollArea(natang)
phuenluean.setGeometry(5,5,100,100)
phuenluean.setStyleSheet('background-color: #c3febd')
phuenluean.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # ตั้งให้แนวตั้งไมีแถบเลื่อน
phuenluean.setLineWidth(3)
phuenluean.setFrameShape(QFrame.Box)

siliam = QLabel('■')
siliam.setStyleSheet('color: #b12661; font-size: 150px')
phuenluean.setWidget(siliam)

natang.show()
qAp.exec_()

จะได้พื้นที่เลื่อนแบบนี้ ซึ่งจะเห็นว่าทั้งแนวตั้วและแนวนอนล้วนมีขนาดเกิน แต่แต่ในแนวตั้งไม่มีแถบเลื่อนเพราะตั้ง Qt.ScrollBarAlwaysOff ไว้ แต่แม้ว่าจะไม่มีแถบเลื่อนปรากฏอยู่ให้เห็นก็สามารถจะใช้ปุ่มกลางของเมาส์เพื่อนหมุนเลื่อนได้อยู่ ลองเลื่อนดูได้






การปรับแต่งแถบเลื่อนแนวนอนและแนวตั้ง {.setHorizontalScrollBar .setVerticalScrollBar}

แถบเลื่อนในแนวนอนและแนวตั้งที่อยู่ด้านล่างและขวาของพื้นที่เลื่อนได้นั้นจริงๆแล้วก็คือตัว QScrollBar ซึ่งเขียนถึงไปในบทที่ ๑๕ นั่นเอง

ปกติแล้ว QScrollBar ๒ อันจะถูกสร้างขึ้นมาให้โดยอัตโนมัติอยู่แล้วเมื่อสร้าง QScrollArea ขึ้น แต่ก็สามารถสร้างใหม่ใส่เข้าไปเองได้ โดยใช้ .setHorizontalScrollBar และ .setVerticalScrollBar

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

ตัวอย่างเช่น ลองสร้างแถบเลื่อนทั้งแนวตั้งและแนวนอนขึ้นมาใหม่ แล้วใส่สีให้แยกกัน
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QLabel,QScrollArea,QScrollBar

qAp = QApplication(sys.argv)
natang = QWidget()

phuenluean = QScrollArea(natang)
phuenluean.setGeometry(10,10,420,300)

khokhwam = QLabel('พื้นที่\nเลื่อนได้')
khokhwam.setStyleSheet('font-family: Tahoma; font-size: 150px; color: #155')
phuenluean.setWidget(khokhwam)

thaeplueannon = QScrollBar() # แถบเลื่อนแนวนอน
thaeplueannon.setStyleSheet('background-color: #a885ee')
phuenluean.setHorizontalScrollBar(thaeplueannon)

thaeplueantang = QScrollBar() # แถบเลื่อนแนวตั้ง
thaeplueantang.setStyleSheet('background-color: #ee859e')
phuenluean.setVerticalScrollBar(thaeplueantang)

natang.show()
qAp.exec_()

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






การตั้งค่าตำแหน่งที่เลื่อนภายในพื้นที่เลื่อน {.setValue}

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

เช่นลองสร้างพื้นที่เลื่อนขึ้นมาพร้อมกับปุ่มที่ถ้ากดแล้วให้ตำแหน่งของแถบเลื่อนจะไปอยู่จุดเริ่มต้น ทำให้ตำแหน่งในพื้นที่เลื่อนกลับไปอยู่ซ้ายบนด้วย
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QLabel,QScrollArea,QScrollBar,QHBoxLayout,QPushButton

qAp = QApplication(sys.argv)
natang = QWidget()
hbl = QHBoxLayout()
natang.setLayout(hbl)

phuenluean = QScrollArea(natang)
hbl.addWidget(phuenluean)
phuenluean.setFixedSize(120,100)

thaeplueannon = QScrollBar() # แถบเลื่อนแนวนอน
phuenluean.setHorizontalScrollBar(thaeplueannon)
thaeplueannon.setStyleSheet('background-color: #bdf')

thaeplueantang = QScrollBar() # แถบเลื่อนแนวตั้ง
phuenluean.setVerticalScrollBar(thaeplueantang)
thaeplueantang.setStyleSheet('background-color: #efb')

siliam = QLabel()
siliam.setFixedSize(400,300)
phuenluean.setWidget(siliam)

# สร้างปุ่มที่เมื่อกดปุ่มแล้วให้เลื่อนกลับไปอยู่ที่ตำแหน่ง 0,0 (คือมุมซ้ายบน)
def paibonsai():
    thaeplueannon.setValue(0)
    thaeplueantang.setValue(0)
pum = QPushButton('0')
pum.setFixedSize(50,50)
hbl.addWidget(pum)
pum.clicked.connect(paibonsai)

print(thaeplueannon.maximum()) # พิมพ์ค่าสูงสุดแนวนอน
print(thaeplueantang.maximum()) # พิมพ์ค่าสูงสุดแนวตั้ง
# ตั้งตำแหน่งในตัวเลื่อนตอนเริ่มต้น
thaeplueannon.setValue(int(thaeplueannon.maximum()/2)) # ตั้งให้แนวนอนเลื่อนไปอยู่ตรงกลาง
thaeplueantang.setValue(int(thaeplueantang.maximum())) # ตั้งให้เลื่อนไปอยู่ล่างสุด

natang.show()
qAp.exec_()

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






การสร้างช่องแบ่งที่เลื่อนปรับขนาดได้ {QSplitter}

หากต้องการสร้างพื้นที่ที่แบ่งส่วนโดยสามารถเลื่อนเพื่อปรับขนาดได้ อาจทำได้โดยใช้ QSplitter

วิธีการใช้จะคล้ายกับการสร้างโครงด้วย QHBoxLayout หรือ QVBoxLayout แต่จะเลื่อนปรับขนาดได้อย่างอิสระ

เวลาที่สร้างให้ใส่ Qt.Horizontal หรือ Qt.Vertical เพื่อกำหนดว่าจะให้แบ่งแนวนอนหรือว่าแนวตั้ง

ตัวอย่างกรณีที่แบ่งในแนวนอน
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QSplitter,QPushButton
from PyQt5.QtCore import Qt
    
qAp = QApplication(sys.argv)
natang = QWidget()
natang.setStyleSheet('font-family: Courier New; font-size: 19px;')
baengsaikhwa = QSplitter(Qt.Horizontal,natang) # สร้างช่องแบ่งตามซ้ายขวา
baengsaikhwa.setGeometry(10,10,360,140)
baengsaikhwa.addWidget(QPushButton('ซ้าย'))
baengsaikhwa.addWidget(QPushButton('กลาง'))
baengsaikhwa.addWidget(QPushButton('ขวา'))
natang.show()
qAp.exec()

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



ลองดูอีกตัวอย่าง คราวนี้เป็นในกรณีที่แบ่งตามแนวตั้ง
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QSplitter,QPushButton
from PyQt5.QtCore import Qt
    
qAp = QApplication(sys.argv)
natang = QWidget()
baengbonlang = QSplitter(Qt.Vertical,natang) # สร้างช่องแบ่งตามบนล่าง
baengbonlang.setGeometry(10,10,150,240)
for i in range(1,6): # วนซ้ำเพื่อไล่ใส่ปุ่มที่มีเลข 1 ถึง 5
    baengbonlang.addWidget(QPushButton('%d'%i))
natang.show()
qAp.exec()

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





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





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

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

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

หมวดหมู่

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

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

目次

日本による名言集
モジュール
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
機械学習
-- ニューラル
     ネットワーク
javascript
モンゴル語
言語学
maya
確率論
日本での日記
中国での日記
-- 北京での日記
-- 香港での日記
-- 澳門での日記
台灣での日記
北欧での日記
他の国での日記
qiita
その他の記事

記事の類別



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

  記事を検索

  おすすめの記事

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

ไทย

日本語

中文