ต่อจาก
บทที่ ๑๕
ในบทนี้จะพูดถึงเรื่องการสร้างพื้นที่ซึ่งสามารถเลื่อนไปมาเพื่อดูส่วนต่างๆได้ ซึ่งมีประโยชน์เวลาที่มีพื้นที่อยู่จำกัด
ทำให้สามารถวางของที่ใหญ่กว่าพื้นที่ที่มีอยู่ได้
การสร้างพื้นที่เลื่อนได้ {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()
ก็จะได้ ๕ ปุ่มที่แบ่งกันอยู่ในแนวตั้งแบบนี้ สามารถลองคลิกลากเพื่อปรับขนาดแต่ละช่องดูได้
อ่านบทถัดไป >>
บทที่ ๑๗