導讀
單選按鈕(QRadioButton)和復選框(QCheckBox)是界面設計中的重要元素。單選按鈕只允許用戶在一組選項中選擇一個,且當其中一個被選中的時候,按鈕組中的其他單選按鈕自動取消。復選框則可以讓用戶同時選中多個選項,這在多項選擇的情況下非常有用。此外,復選框經過設置還具備第三種狀態:未決狀態(partially checked)。單選按鈕和復選框應用廣泛,在WEB表單、軟件配置界面常常是不可或缺的元素。這篇博文主要講述Qt中單選按鈕和復選框如何通過樣式表進行外觀定制。
基本實現
單選按鈕(QRadioButton)的基本特征是互斥。當一個按鈕選中,系統自動取消其他按鈕的選中狀態。當然,前提是這些按鈕都要放置同一個父組件(Parent Widget)中。我們簡單的用Qt Designer拖個按鈕組,按Ctrl+R進行預覽:
效果還不錯,朴素簡單。在這里,我們將一組單選按鈕全部放到了一個QGroupBox里面。這樣,當一個按鈕選中的時候其他選中的按鈕將被自動取消。但是缺點是:如果我們想要獲取當前被選中的按鈕是哪一個,不太方便判斷。一個簡單而粗暴的方法是,循環遍歷每個單選按鈕的狀態進行檢查。顯然這樣的方法太笨拙。另外的一個方法是,將這一組單選按鈕全部添加到QButtonGroup中去。QButtonGroup是一個容器組件,在Qt Designer中我們找不到這個組件,因為它是不可見的,僅僅是在后台工作的無名英雄。因此,我們需要做的是將所有的單選按鈕添加進去,之后通過QButtonGroup的方法可以快速查詢按鈕狀態。具體參見《QT中獲取選中的radioButton的兩種方法》及《QT中根據ID設置radio按鈕》。
如何進行樣式定制呢?QRadioButton定制分成兩個兩個部分:選中按鈕和文本。其中我們重點要定制的就是選中按鈕,為此我們需要准備一些狀態圖片。看看Qt幫助手冊的內容:
QRadioButton::indicator { # indicator是一個子組件,這里的width和height分別指定按鈕的寬和高 width: 13px; height: 13px; } QRadioButton::indicator::unchecked { # 未選中時狀態,也即正常狀態 image: url(:/images/radiobutton_unchecked.png); } QRadioButton::indicator:unchecked:hover { # 未選中時,鼠標懸停時的狀態 image: url(:/images/radiobutton_unchecked_hover.png); } QRadioButton::indicator:unchecked:pressed { #未選中時,按鈕下按時的狀態 image: url(:/images/radiobutton_unchecked_pressed.png); } QRadioButton::indicator::checked { # 按鈕選中時的狀態 image: url(:/images/radiobutton_checked.png); } QRadioButton::indicator:checked:hover { # 按鈕選中時,鼠標懸停狀態 image: url(:/images/radiobutton_checked_hover.png); } QRadioButton::indicator:checked:pressed { # 按鈕選中時,鼠標下按時的狀態 image: url(:/images/radiobutton_checked_pressed.png); }
看上面的幾條樣式語句,我們顯然要准備六張圖片。利用不同的偽狀態設置單選按鈕的::indicator子組件。找圖片是一件困難的事情,因此我只准備了四張圖片。按鈕下按時就不設置圖片了:
我們自己編寫的QSS代碼如下:
QRadioButton { spacing: 5px; font-size: 14px; color: rgb(24, 220, 88); # 連同 font-size一齊設置按鈕的文本樣式 } QRadioButton::indicator { # 設置為我們圖片的大小 width: 15px; height: 15px } QRadioButton::indicator:checked { # 按鈕選中的狀態 image: url(:/buttonbg/radio_down); } QRadioButton::indicator:disabled { # 按鈕禁用時的狀態 image: url(:/buttonbg/radio_disable); } QRadioButton::indicator:unchecked { # 未選中時的狀態 image: url(:/buttonbg/radio_normal); } QRadioButton::indicator:unchecked:hover { # 未選中時的鼠標懸停狀態 image: url(:/buttonbg/radio_hover); }
最終效果如下:
當然,圖片還可以換成方形的。不過傳統設計中單選按鈕都設計成了原型,這里的圖片來自金山衛士。相比於復選框(QCheckBox),單選按鈕少了一個狀態:indeterminate。通過我們QCheckBox的setTristate()可以將一個復選框設置成indeterminate狀態。對於復選框我們編寫如下的QSS代碼:
QCheckBox { spacing: 5px; # 在這里我們也可以設置復選的文本樣式 } QCheckBox::indicator { width: 15px; height: 15px; } QCheckBox::indicator:unchecked { image: url(:/buttonbg/checkbox_normal); } QCheckBox::indicator:unchecked:disabled { image: url(:/buttonbg/checkbox_disable); } QCheckBox::indicator:unchecked:hover { image: url(:/buttonbg/checkbox_hover); } QCheckBox::indicator:checked { image: url(:/buttonbg/checkbox_down); } QCheckBox::indicator:indeterminate { image: url(:/buttonbg/checkbox_indeterminate); }
可以看到,基本定制方法和QRadioButton一樣,只是多了一個indeterminate狀態:
其中,Ruby復選框被設置成了禁用,而python復選框則設置為了indeterminate狀態。外觀上並沒有太大的變化。如果要改變復選框的文本樣式,也可以和上面QRadioButton一樣設置。總的來說,QRadioButton和QCheckBox的定制還是挺簡單的,任務量不大,因為其本身也足夠簡單。
效果對比
最終的效果對比下:
總結
1. 樣式定制的重點是::indicator,利用偽狀態為::indicator設置好不同狀態時的背景圖片。
2. 理解QRadioButton和QCheckBox的不同狀態。