QSS ( Qt Style Sheet ) 樣式設定
QSS 是 PyQt6 裡用來設定元件樣式的樣式表 ( Qt Style Sheet ),使用方法和網頁 CSS 非常類似,雖然 QSS 沒有辦法像網頁 CSS 般的完整,但已經可以滿足大部分的樣式設計需求,這篇教學會介紹如何使用 QSS 設定元件樣式。
快速導覽:
因為 Google Colab 不支援 PyQt6,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda )。
開始使用 QSS
在 PyQt6 裡建立元件之後,元件會具有一個 setStyleSheet() 方法,在方法裡撰寫樣式,就會修改原本元件的樣式,例如下方的程式碼執行後,就會將 QLabel 的文字設定為 30px 的大小和紅色 ( 如果遇到多個樣式,可以使用三個單引號的方式撰寫 )。
from PyQt6 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
label = QtWidgets.QLabel(Form)
label.setGeometry(10,10,150,100)
label.setText('HELLO')
label.setStyleSheet('''
font-size:30px;
color:red;
''')
Form.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
self.label = QtWidgets.QLabel(self)
self.label.setGeometry(10,10,150,100)
self.label.setText('HELLO')
self.label.setStyleSheet('''
font-size:30px;
color:red;
''')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
常用樣式設定
下方列出一些常用的樣式 ( 完整屬性參考「List of Properties」)。
樣式 | 說明 |
---|---|
font-size | 文字大小,單位 px。 |
color | 文字顏色,可使用顏色名稱或色碼,例如 #f00 為紅色。 |
font-family | 字體。 |
font-weight | 字體粗細,可設定 normal、bold。 |
font-style | 文字樣式,可設定 normal、italic、oblique。 |
spacing | 文字間距,不用單位。 |
text-align | 文字對齊方式,可設定 left、center、right。 |
height | 元件高度,單位 px。 |
width | 元件寬度,單位 px。 |
margin | 元件外邊距,單位 px。 |
padding | 元件內邊距,單位 px。 |
opacity | 透明度,範圍 0~255,0 為透明。 |
background | 背景色或背景圖,可使用顏色名稱或色碼,例如 #f00 為紅色。 |
background-color | 背景色,可使用顏色名稱或色碼,例如 #f00 為紅色。 |
border | 邊框,有三個值分別是 ( 粗細、樣式、顏色 )。 |
border-width | 邊框寬度,單位 px。 |
border-style | 邊框樣式,可設定 solid、dashed、dotted。 |
border-color | 邊框顏色,可使用顏色名稱或色碼,例如 #f00 為紅色。 |
border-radius | 邊框是否圓角,圓角半徑單位 px。 |
樣式裡的 padding、margin、border-width、border-style、border-color 的簡單設定規則如下 ( 以 padding 為例 ):
寫法 | 說明 |
---|---|
padding:1px | 上下左右都 1px。 |
padding:1px 2px | 上下 1px,左右 2px。 |
padding:1px 2px 3px | 上 1px,左右 2px,下 3px。 |
padding:1px 2px 3px 4px | 上 1px,右 2px,下 3px,左 4px。 |
如果不要一次設定 padding、margin、border、border-width、border-style、border-color,也可以加上方向的名稱單獨設定 ( 以 padding 為例 ):
樣式 | 說明 |
---|---|
padding-top | 元件上方內邊距,單位 px。 |
padding-right | 元件右側內邊距,單位 px。 |
padding-bottom | 元件下方內邊距,單位 px。 |
padding-left | 元件左側內邊距,單位 px。 |
偽狀態設定
除了設定主要樣式,QSS 也像 CSS 一樣可以設定「偽狀態」( Pseudo-States ),偽類的意思是「觸發了某些事件或進行某些行為後,才會出現的狀態」 ( 偽類會使用一個冒號開頭 ),例如「滑鼠移到按鈕上」的行為,對應的偽狀態就是「:hover」,下方列出一些常見的偽狀態 ( 完整偽狀態參考「List of Pseudo-States」 ):
偽狀態 | 說明 |
---|---|
:hover | 滑鼠移上去。 |
:active | 發生行為 ( 通常可能是點擊 )。 |
:focus | 成為焦點 ( 通常是點擊之後 )。 |
:checked | 被勾選。 |
:disabled | 停用狀態。 |
:enabled | 啟用狀態。 |
:selected | 被選取。 |
以下方的程式碼為例,執行後會設定 QPushButton 的 :hover 樣式 ( 注意需要額外使用 QPushButton:hover ),當滑鼠移動到按鈕上方時,按鈕的邊框會變粗,背景色會變成黃色。
from PyQt6 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
btn = QtWidgets.QPushButton(Form)
btn.setGeometry(10,10,150,100)
btn.setText('HELLO')
btn.setStyleSheet('''
QPushButton{
border:1px solid #000;
background:#fff;
}
QPushButton:hover{
border:5px solid #000;
background:#ff0;
}
''')
Form.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
self.btn = QtWidgets.QPushButton(self)
self.btn.setGeometry(10,10,150,100)
self.btn.setText('HELLO')
self.btn.setStyleSheet('''
QPushButton{
border:1px solid #000;
background:#fff;
}
QPushButton:hover{
border:5px solid #000;
background:#ff0;
}
''')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
子控制項設定
在 PyQt6 裡,有些元件可能會包含其他的子控制項 ( 例如 QListWidget 列表選擇框會包含選項的子元件 ),這些子元件也可以使用對應的 QSS 語法設定樣式 ( 子控制項會使用兩個冒號開頭 ),下方列出一些常見的子元件設定方法 ( 完整子元件設定參考「List of Sub-Controls」 ):
子控制項 | 說明 |
---|---|
::chunk | 進度條進度。 |
::item | 列表選擇框項目。 |
::groove | 滑桿底線。 |
::handle | 滑桿拉霸。 |
::sub-page | 滑桿調整線。 |
下方的程式碼執行後,會將 QSlider 數值調整滑桿更改為黑底線與紅色調整桿。
from PyQt6 import QtWidgets, QtCore
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
slider = QtWidgets.QSlider(Form)
slider.setGeometry(20,20,200,30)
slider.setOrientation(QtCore.Qt.Orientation.Horizontal)
slider.setStyleSheet('''
QSlider {
border-radius: 10px;
}
QSlider::groove:horizontal {
height: 5px;
background: #000;
}
QSlider::handle:horizontal{
background: #f00;
width: 16px;
height: 16px;
margin:-6px 0;
border-radius:8px;
}
QSlider::sub-page:horizontal{
background:#f90;
}
''')
Form.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets, QtCore
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
self.slider = QtWidgets.QSlider(self)
self.slider.setGeometry(20,20,200,30)
self.slider.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.slider.setStyleSheet('''
QSlider {
border-radius: 10px;
}
QSlider::groove:horizontal {
height: 5px;
background: #000;
}
QSlider::handle:horizontal{
background: #f00;
width: 16px;
height: 16px;
margin:-6px 0;
border-radius:8px;
}
QSlider::sub-page:horizontal{
background:#f90;
}
''')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
注意事項
雖然使用 QSS 可以很方便的修改樣式,但仍然有些小細節需要注意,例如 QPushButton,一旦設定了「邊框」,則必須要一併設定背景色和點擊樣式,不然其他樣式就會被清空,類似這種狀況可以參考「Qt Style Sheets Reference」裡有特別標注「粉紅色背景」的說明。
下方的程式碼執行後,會發現本來按鈕的點擊效果,因為設定了 border 樣式而消失了。
from PyQt6 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
btn = QtWidgets.QPushButton(Form)
btn.setGeometry(10,10,150,100)
btn.setText('HELLO')
btn.setStyleSheet('border:1px solid #000')
Form.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets, QtCore
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
def ui(self):
self.btn = QtWidgets.QPushButton(self)
self.btn.setGeometry(10,10,150,100)
self.btn.setText('HELLO')
self.btn.setStyleSheet('border:1px solid #000')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
參考資料
完整 QSS 說明可以參考:Qt Style Sheets Reference
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~