這篇文章來自於QT的幫助文檔,你要是看了最新版的,會發現講解得更棒。如果你的英文不是那么好,或者說看着頭疼,那還是來看此篇吧。
在此之前說一個幫助文檔的特別用法,絕不僅僅是搜單詞,QT的文檔非常強大的,比如你要搜索怎么使用qss,可以這樣搜索:how to use stylesheet
本文轉載,原地址為:http://blog.csdn.net/markely/article/details/7881203
三 通過Qt4.2樣式表定制程序外觀
目錄
1. 何為Qt樣式表
2. 樣式表語法基礎
3. 方箱模型
4. 前景與背景
5. 創建可縮放樣式
6. 控制大小
7. 處理偽狀態
8. 使用子部件定義微觀樣式
8.1. 相對定位
8.2. 絕對定位
摘要
由於Qt樣式表的引入,定制Qt部件的外觀樣式變得非常簡單。 無論你是想僅僅修改一個現有部件的外觀,還是想從零開始設計一套全新的界面風格, 現在都有了一種新的方法而不必再去繼承並實現一個QStyle的子類。
1. 何為Qt樣式表
Qt樣式表的思想很大程度上是來自於HTML的層疊式樣式表(CSS), 通過調用QWidget::setStyleSheet()或QApplication::setStyleSheet(), 你可以為一個獨立的子部件、整個窗口,甚至是整個個應用程序指定一個樣式表。
樣式表是通過QStyle的一個叫做QStyleSheetStyle的特殊子類來實現的。 這個特殊的子類實際上是其他的系統特定風格類的包裹類, 它會把通過樣式表指定的自定義外觀風格應用在底層的系統特定風格之上。
Qt 4.2包含了一個叫做stylesheet的例子來幫助你學習樣式表, 這個例子自帶了兩個樣式:Coffee和Pagefold。
上面的Coffee風格自定義了push button、frames和tooltip,但使用了下層的風格 (例如這里是Windows XP風格)來繪制checkbox,combobox和radio button。
Pagefold風格完全重新定義了對話框中使用的所有控件的外觀,從而實現了一種獨特的,平台無關的外觀。
2. 樣式表語法基礎
Qt樣式表與CSS的語法規則幾乎完全相同,如果你已經了解了CSS,完全可以跳過本節。
一個樣式表由一系列的樣式規則構成。每個樣式規則都有着下面的形式:
selector { attribute: value }
選擇器(selector)部分通常是一個類名(例如QComboBox),當然也還有其他的語法形式。
屬性(attribute)部分是一個樣式表屬性的名字,值(value)部分是賦給該屬性的值。
為了使用方便,我們還可以使用一種簡化形式:
selector1, selector2, ..., selectorM {
attribute1: value1;
attribute2: value2;
...
attributeN: valueN;
}
這種簡化形式可以同時為與M個選擇器相匹配的部件設置N種屬性。例如:
QCheckBox, QComboBox, QSpinBox {
color: red;
font: bold;
}
這個規則設置了所有的QCheckBox、QComboBox和QSpinBox的前景色、背景色和字體。
在線文檔列出了每種部件支持的所有屬性。在本文中,我們只使用最常見的幾種通用屬性。
3. 方箱模型
在樣式表中,每個部件都被看作是一個由四個同心相似的矩形組成的箱體:空白(margin)、邊框(border)、填充(padding)和內容(content)。對於一個平面部件——例如一個空白、邊框和填充都是0像素的部件——而言,這四個矩形是完全重合的。
空白區域位於邊框外,並且總是透明的。邊框為部件提供了四周的框架,其border-style屬性可以設置為一些內置的框架風格,如inset、outset、solid和ridge。填充在邊框和內容區域之間提供了空白間隔。
4. 前景與背景
部件的前景色用於繪制上面的文本,可以通過color屬性指定。背景色用於繪制部件的填充矩形,可以通過background-color屬性指定。
背景圖片使用background-image屬性定義,它用於繪制由background-origin指定的矩形區域(空白、邊框、填充或內容)。背景圖片在矩形區域內的對齊和平鋪方式可以通過background-position和background-repeat屬性指定。
如果指定的背景圖片具有alpha通道(即有半透明效果),通過background-color指定的顏色將會透過透明區域。這一功能可以使背景圖片在多種環境下重復利用。
該例子中使用的樣式表如下所示:
QFrame {
margin: 10px;
border: 2px solid green;
padding: 20px;
background-image: url(qt.png);
background-position: top right;
background-origin: content;
background-repeat: none;
}
在這個例子中,QFrame四周的空白、邊框和填充值都是一樣的。實際上margin屬性可以在上下左右四個方向分別指定我們需要的不同值,例如:
QFrame {
margin: 14px 18px 20px 18px;
}
同時,我們也可以分別指定margin-top、margin-right、margin-bottom、margin-left四個屬性。
QFrame {
margin-top: 14px;
margin-right: 18px;
margin-bottom: 20px;
margin-left: 18px;
}
雖然目前我們僅僅使用了QFrame作為例子,但是我們也可以同樣的將這些屬性應用於任何一個支持方箱模型的Qt部件,例如:QCheckBox、 QLabel、QLineEdit、QListView、QMenu、QPushButton、QTextEdit、和QToolTip。
5. 創建可縮放樣式
在默認情況下,通過background-image指定的背景圖片會自動重復平鋪,以覆蓋部件的整個填充矩形(即邊框里面的那個區域)。如果我們想創建能夠隨着部件大小自動縮放而不是平鋪的背景,我們需要設置一種稱之為“邊框圖片”的東東。
“邊框圖片”可以通過border-image屬性指定,它同時提供了部件的背景和邊框。一個“邊框圖片”被分為九個部分(九宮格),有點向tic-tac-toe游戲的棋盤。
當一個部件的邊框被填充時,四角的格子通常不會發生變化,而其余的五個格子則可能被拉伸或平鋪以填充可用空間。
當指定一個“邊框圖片”時,除了圖片本身,我們還必須指定用來分割九宮格的四條分割線。同時我們還必須指定非邊角的格子是應該平鋪還是拉伸,以及邊框的寬度(用來確定邊角格子的大小,防止邊角被縮放變形)。
例如,下面的樣式表定義了上圖中的button:
QPushButton {
border-width: 4px;
border-image: url(button.png) 4 4 4 4 stretch stretch;
}
另外,“邊框圖片”還應該含有alpha通道,以使背景能夠在邊角處露出來。
6. 控制大小
min-width和min-height兩個屬性可以用來指定一個部件的內容區域的最小大小。這兩個值將影響部件的minimumSizeHint(),並在布局時被考慮。
例如:
QPushButton {
min-width: 68px;
min-height: 28px;
}
如果該屬性沒有被指定,最小大小將從部件的內容區域和當前樣式中繼承。
7. 處理偽狀態
部件的外觀可以按照用戶界面元素狀態的不同來分別定義,這在樣式表中被稱為“偽狀態”。例如,如果我們想在一個push button在被按下的時候具有sunken的外觀,我們可以指定一個叫做 :pressed 的偽狀態。
QPushButton {
border: 2px outset green;
background: gray;
}
QPushButton:pressed {
border-style: inset;
}
下面是可用的偽狀態列表:
表 1. 偽狀態列表
偽狀態 描述
:checked button部件被選中
:disabled 部件被禁用
:enabled 部件被啟用
:focus 部件獲得焦點
:hover 鼠標位於部件上
:indeterminate checkbox或radiobutton被部分選中
:off 部件可以切換,且處於off狀態
:on 部件可以切換,且處於on狀態
:pressed 部件被鼠標按下
:unchecked button部件未被選中
8. 使用子部件定義微觀樣式
許多部件都包含有子元素,這些元素可以稱為“子部件”。Spin box的上下箭頭就是子部件最好的例子。
子部件可以通過::來指定,例如QDateTimeEdit::up-button。定義子部件的樣式與定義部件非常相似,它們遵循前面提到的方箱模型(即它們可以擁有自己的邊框、背景等),並且也可以和偽狀態聯合使用(例如QSpinBox::up-button:hover)。
下表列出了可用的子部件類型:
表 2. 子部件列表
子部件 描述
::down-arrow combo box或spin box的下拉箭頭
::down-button spin box的向下按鈕
::drop-down combo box的下拉箭頭
::indicator checkbox、radio button或可選擇group box的指示器
::item menu、menu bar或status bar的子項目
::menu-indicator push button的菜單指示器
::title group box的標題
::up-arrow spin box的向上箭頭
::up-button spin box的向上按鈕
通過指定subcontrol-position和subcontrol-origin屬性,子部件可以被放置在部件箱體內的任何位置。並且,子部件的位置還可以使用相對或絕對的方式進一步的調整。具體選擇何種調整方式取決於子部件具有固定的大小,還是會隨着父部件而變化。
8.1. 相對定位
相對定位適合於子部件具有固定大小的情形(通過width和height指定子部件大小)。使用這種方式,子部件可以以相對於subcontrol-position和 subcontrol-origin屬性定義的原始位置進行移動調整。使用left屬性可以把子部件向右移,top屬性可以把子部件向左移。
例如:
QPushButton::menu-indicator {
image: url(menu_indicator.png);
width: 13px;
height: 13px;
subcontrol-origin: padding;
subcontrol-position: bottom right;
}
當按下按鈕時,我們可以把菜單指示器從原來的位置向右下方移動幾個像素來模擬按鈕按下的狀態。
QPushButton::menu-indicator:pressed {
position: relative;
top: 2px;
left: 2px;
}
8.2. 絕對定位
絕對定位適合於子部件的位置隨父部件的變化而變的情形。與前面的例子相同,subcontrol-origin定義了父部件箱體的參考矩形。子部件的矩形區域則可以隨后通過相對於這個參考矩形四邊的偏移量來定義。
QPushButton::menu-indicator {
border: 2px solid red;
subcontrol-origin: padding;
position: absolute;
top: 2px;
right: 2px;
bottom: 2px;
left: 40px;
}
對於寬度或高度固定的子部件,subcontrol-position被用來說明其在subcontrol-origin指定矩形內的對其方式:
QPushButton::menu-indicator {
image: url(menu_indicator.png);
width: 13px;
subcontrol-origin: padding;
subcontrol-position: bottom right;
position: absolute;
top: 2px;
bottom: 2px;
right: 2px;
}
四 http://doc.qt.nokia.com/4.6/stylesheet-examples.html#customizing-qdockwidget
五 樣式表使用
雖然Qt現在還不是特別完善,但它的跨平台性,界面重用性,已經表現出比mfc更強的、更好的性能,昨天寫了qss樣式表demo,但是在書上對樣式表的使用,並不詳細,初學者可能會遇到一些問題,今天對照官方代碼,終於調通,簡單記錄如下:
1、建立文本文件,寫入樣式表內容,更改文件后綴名為qss;
2、在工程中新建資源文件*.qrc,將qss文件加入資源文件qrc中,此處注意prefix最好為"/",否則在調用qss文件時會找不到文件;
3、通過傳入路徑\文件名的方式創建一個QFile對象,以readonly的方式打開,然后readAll,最后qApp->setStyleSheet就可以使qss生效。
樣式表的方式可以很方便的完成簡單的貼圖工作,而且效果也不錯,簡化了我以前在mfc上為了貼圖,不得不重寫控件類個工作,也使得美工可以很方便的修改生成的程序的顏色。
當今年4月初的時候,NOKIA收購了Qt,並推出了Qt4.2,當時並沒有太注意,而當mfc開發的界面不能滿足我的時候,我才去研究這個新的技術。
Qt很爽,因為是C++語言,所以看起來很快,預計在明年一月底,我就可以完全掌握,而且也因為是C++代碼級跨平台,所以也獲得了很高的執行效率。而它生成控件的方式則比mfc上的資源文件好得多,mfc中的窗體資源全部在一個.src文件中,不利於重用,而Qt中每個窗體擁有自己的資源文件,並且和窗體類是分開的,方便了重用。從此,我不在被局限於windows平台。
我會研究一下如何在應用程序中完成widget部件的使用,因為那種透明、隨意拖拽的自定義部件必將是下一代UI主流。
QApplication app(...);
QFile qss("stylesheet.qss");
qss.open(QFile::ReadOnly);
app.setStyleSheet(qss.readAll());
qss.close();
轉自:http://blog.csdn.net/xuancailinggan/article/details/50429840