QSS常用於Qt的控件樣式美化,合理地使用Qss可以完成在不改動代碼的情況下改變Qt界面的樣式。
官方提供的例子: http://qt-project.org/doc/qt-4.8/stylesheet-examples.html
這個是官方提供的例子,只有qt-4.8的,目前Qt最新版本是Qt5.4,但似乎在qss這塊沒有較大的更新,同時有關幫助手冊可以在Qt Assistant中尋找。
在這個Qt Style Sheets Reference中有QSS所支持的所有屬性、狀態,QSS是參照CSS2的,但並非所有的CSS2屬性QSS都支持,具體支不支持就需要查一下幫助手冊了。
QSS的語法和CSS的語法保持一致
selector {declaratin1; declaratin2; ...declaratinN; }
拿最簡單的QPushButton來看
QPushButton { // selector color: red; // \ border: none; // / declaration }
declaration部分就是一系列的properties: values
在使用屬性:值的時候曾經碰到過一個小問題。
QLabel { background: url ("xxxx"); // 如果在url后面有空格,這句屬性將不起效果 }
由於自己在寫C/C++代碼的時候有在函數名后加空格的習慣,導致了這個錯誤,需要注意一下。
上面直接使用QPushButton或是QLabel將會對所有的該類控件引起效果,有些時候我們並不希望這樣,所以這個時候需要指定選擇器來區分要操作的對象。
關於選擇器的一些介紹可以看這篇博文,雖然也是轉載的http://www.cnblogs.com/davesla/archive/2011/01/30/1947928.html
稍微總結一下常用的。
QSS 中最常用的當屬ID選擇器了,用#號區分
QLabel#thisIsLabel { color: red; }
用了ID選擇器以后,將只會有這個ID對應的控件會產生樣式效果。拿這個ID怎么來的呢?一般通過setObjectName指定的,像對這個QLabel進行設置,就必須在代碼中加上thisIsLabel->setObjectName ("thisIsLabel");
但通常從Designer中命名好的控件不用特意加上setObjectName是因為在系統生成的ui頭文件中已經幫你做了這件事兒了,所以在用的時候千萬不能QLabel#ui->thisIsLabel 這樣,ui是命名控件,這樣寫是非法的。
屬性選擇器有些時候也會有妙用,比如當你的一個控件需要因為一個屬性的改變而希望樣式改變的時候,就需要用到屬性選擇器。
QLabel#thisIsLabel[enable=true] { color: red; } QLabel#thisIsLabel[enable=false] { color: blue; }
[] 中括號內部的就是選擇的屬性,屬性名和value都需要通過setProperty這個函數實現。
下面這個是Qt Assistant關於這個函數的介紹,這個函數除了指定屬性為QSS服務以外還有很多其他的用法,這里暫不做討論。
我基本上就使用這兩種選擇器能完成大部分的設計了。
然后就是一些子控件選擇器了,如 QAbstractItemView 的::item, QScrollBar的::handle。
這些以::開頭的都表示控件的子控件選擇器,為什么說是子控件,因為一個控件可能是由多個子控件組成的,我們在改變樣式的時候自然也希望改變其子控件的樣式。
像:hover, :pressed, :checked這些都是偽指示器,活用這些可以實現控件的三態效果(普通,懸停,按下),但要注意的是並不是所有的控件都會有這些效果的,QLabel就沒有,但如果想實現QLabel的三態效果也不是不可以,可以使用事件過濾器去捕獲QLabel的enterEvent和leaveEvent實現hover,使用mousePressEvent實現pressed,只是QLabel本身是不支持的,具體哪些控件支持哪些功能,可以查閱Qt Style Sheets Reference
偽指示器也是支持!(否定符號)的
QPushButton#myBtn:!pressed { color: red; }
這樣就表示在鼠標沒有按下的情況下字體顏色是紅色的。
掌握QSS的基礎知識 + 懂CSS2語法基本就能進行QSS樣式設計了。
QSS在代碼中可以通過setStyleSheet ();的方式將樣式設置進去,但同時也可以通過加載樣式文件的方式,我通常喜歡把所有的QSS放在xxx.qss文件中進行統一管理。
QApplication a (argc, argv);
File_operate file_opt;
QByteArray array = file_opt.read_file (FILE_STYLE_PATH); array += file_opt.read_file (FILE_STYLE_ADD_PATH); a.setStyleSheet (QLatin1String (array));
File_operate是我根據QFile封裝的一層類,增加了一些日志和判斷
這里我用到了兩個路徑,為了實現換膚的效果,第一個路徑文件里面放置的QSS基礎樣式,而第二個路徑文件里面放置的是要拓展改變的樣式,這樣我可以通過加載不同的文件來實現樣式的快速切換。
在使用QSS的時候還發現了一些小BUG,可能不能算BUG,但如果用CSS習慣將會實現不了的功能。
有這樣一張圖片
圖片的尺寸是260*32, 而我希望在26*32的一個label上面顯示這張圖片,我所能想到的兩個屬性是background和border-image
如果拿background來做,就需要用到background-position這個屬性
backgroud:#FFF url(image) no-repeat [fixed | scoll] x y;
#FFF 表示背景色
image 表示圖片資源路徑
no-repeat 表示圖片是否重復
fixed 表示不滑動 scroll 表示滾動 默認為scroll
x y 表示圖片的偏移量,也就是background-position這個屬性
在CSS語法中,x y 可以用百分比或者px表示,也可以使用left、right、top、bottm、center這五種對齊方式
而在這個應用中我采用了這句語法發現是不起效果的
background: url(:/C:/Users/xx/Desktop/days_nums.png) no-repeat fixed 26px 0px;
我希望的顯示1這個數字,實際上沒有任何效果,當然采用百分比的方式
background: url(:/C:/Users/xx/Desktop/days_nums.png) no-repeat fixed 10% 0%;
效果依舊和前一種一樣,而使用對齊方式表示,則生效了
background: url(:/C:/Users/dp/Desktop/days_nums.png) no-repeat fixed right;
這樣就會顯示最右邊的數字9
不知道是否是我“打開方式有誤”,感覺如果不能使用數字和百分比的話我就無法實現我的需求了,這個時候就只能思量border-image這個屬性了,關於border-image,這里有篇非常好的文章解釋了其用法 戳這里
使用border-image實現上面需要的功能,就要利用其剪裁特性,其實就是左一刀右一刀上一刀下一刀,對於border-image而言,剪裁后會留下周圍一圈的切片,可以通過單獨對這些切片處理就獲得了想要的border,看到這個之后發現,如果要實現背景的陰影也只需要拿一張含有陰影的圖片裁剪成九宮格,然后可以隨意擴展top、right、bottom、left的尺寸,再和4個角拼接起來。
border-image: url(:/C:/Users/xx/Desktop/days_nums.png) 0 208 0 26 stretch stretch;
這里的0、208、0、26分別是top、right、bottom、left的裁剪坐標,這句語句所形成的效果是,把1這個數字顯示在了32*26的QLabel上了,可是從上面分享的那篇文章來看,border-image顯示的應該是邊框,不應該是中間那塊,我表示比較納悶,除此之外,這條語句依舊不支持百分比
border-image: url(:/C:/Users/xx/Desktop/days_nums.png) 0% 80% 0% 10% stretch stretch;
這樣原來應該和數字表示的形成一樣的效果,結果發現這條語句也將不起作用,這是否算是QSS遺留的一些BUG呢?
關於這些“BUG”只是自己摸索的,或許哪些地方沒有考慮到,請各位大神指點。
一點點小小的總結,希望對Qt初學者有所幫助,不足之處望指出。