样式和样式适用的窗体
绘制在窗体上的样式改善了GUI的外观和体验。QStyle类是一个用于改善GUI外观和体验的抽象类。Qt内建的窗体就是使用了它来实现几乎所有的绘制,确保他们看起来像是原生的窗体。
Qt内建有很多样式。其他一些样式只是适合于特定的平台。自定义样式作为插件或者通过创建一个样式类的实例生成,通过QApplication::SetStyle()。
为了实现一个新样式,你需要继承一个Qt中已有的样式——一个最接近你想创建的样式并且实现了一部分虚函数。
Widget Styling类
QCDEStyle :CDE外观和体验。
QColor:基于RGB,HSV或者CMYK值的颜色。
QCommonStyle:改善GUI的常规外观和体验。
QCursor:异形的鼠标光标。
QDecorationFactory:创建适用于嵌入式Linux的窗体样式。
QFont:为绘制文本指定字体样式。
QFontDatabase:当前系统中的字体样式的信息。
QGraphicsAnchor:表示QGraphicsAnchorLayout布局中两个控件之间的锚。
QGraphicsAnchorLayout:可以在Graphics View中将控件放在一起的布局。
QMacStyle:Mac OS X样式。
QMotifStyle:Motif样式。
QPalette:包含每个窗体状态所用的颜色组。
QStyle:抽象的基类,用于改善GUI的外观和体验。
QStyleFactory:创建QStyle对象。
QStyleHintReturn:
QStyleHintReturnMask:
QStyleHintReturnVariant:
QStyleOption:保存Style函数使用的参数。
QStylePainter:用于在窗体中绘制QStyle元素的类。
QWindowsStyle:Windows窗体样式。
QWindowsVistaStyle:Windows Vista窗体样式。
QWindowsXPStyle:Windows XP窗体样式。
QStyle的实现
QStyle的API包含绘制窗体的函数,实现常规和复杂任务的静态帮助函数和用于各种计算的函数。样式也帮助窗体实现其内容的布局。此外,它还创建一个包含QBrushes的QPallette。
QStyle绘制图形元素,一个元素可以是一个窗体或者一个窗体部分,像是按钮斜角,窗体框线,滚动条等等。大多数绘制函数包含4个参数:
(1)一个定义了要绘制的元素的枚举值。
(2)一个定义了如何对元素着色的QStyleOption。
(3)一个用于绘制元素的QPainter。
(4)一个用于绘制的窗体。
QSS语法
样式规则
样式表包含一系列的样式规则。样式规则由一个选择器和声明组成。选择器指定了受样式规则影响的窗体。声明指定了需要被设置的属性。
例如:
QPushButton {color: red}
在上面的这个样式规则中,QPushButton就是选择器,{color: red}就是声明。该规则指定了QPushButton和它的子类使用红色作为前景色。
Qt样式表对大小写不敏感。大小写敏感的是类名称,对象名称和Qt属性名称。
多个选择器可以被指定为相同的声明。
例如:
QPushButton, QLineEdit, QComboBox { color : red )
声明可以是一组样式规则。
例如:
QPushButton { color: red; background-color: white}
选择器类型
Qt样式表支持所有CCS2中的样式。
子控件
为了设置完整的窗体样式,需要访问窗体的子控件。选择器可以包含子控件以使用特定的窗体子控件来实现一个应用程序。
例如:
QComboBox::drop-down { image: url(dropdown.png)}
上述规则实现了所有QComboBox控件的drop-button按钮。
子控件通常与其他参考元素无关。参考元素可以是窗体或者其他子控件。例如,QComboBox的drop-down默认被放置在填充矩形的右上角。而在drop-down子控件的内容矩形中,它被放在控件的中央。
可以使用subcontrol-origin属性来改变定位矩形。例如,如果我们想要将drop-down放置在QComboBox的边缘矩形中来代替默认的填充矩形,我们可以如下定义:
QCombox {
margin-right: 20px;
}
QComboBox::drop-down {
subcontrol-origin: margin;
}
drop-down基于边缘矩形的布局可以使用subcontrol-postion属性进行更改。
width和height属性可以用于控制子控件的尺寸。注意:设置一个图片也同时设置了子控件的尺寸。
采用相对位置布局结构,允许子控件的位置从它的初始位置被偏移。例如,当QComboBox的drop-down按钮被按下,我们可能希望箭头被偏移来实现一个按下的效果。为实现该效果,我们进行如下定义:
QComboBox::down-arrow{
image: url(down_arrow.png);
}
QComboBox::down-arrow:pressed{
position: relative;
top: 1px;left: 1px;
}
采用绝对位置布局结构,允许子控件的位置和尺寸不依赖参考元素而被更改。
一旦被定位,子控件将被作为和窗体一样的控件并可使用box model设置样式。
对于复合窗体如QComboBox和QScrollBar,如果一个子控件的属性被自定义,则子控件的其他属性也应该被自定义。
Pseudo-States(伪状态)
选择器可能包含伪状态来表示基于窗体状态的约束规则。伪状态出现在选择器的末尾。例如,下面的规则用于当鼠标经过QPushButton。
QPushButton:hover { color: white}
伪状态可以使用“!”进行取反。例如,下面规则表示当鼠标没有经过QRadioButton。
QRadioButton:!hover { color: red }
伪状态可以使用AND关系。例如,当鼠标经过一个被选择的QCheckBox。
QCheckBox:hover:checked { color: write }
伪状态可以使用OR关系。
QCheckBox:hover, QCheckBox:checked { color: white}
伪状态也可以用于子控件。
QComboBox::drop-down:hover { image: url(dropdown_bright.png)}
解析冲突的解决
当多个样式规则指定到系统属性的值不相同时,则发生解析冲突。
例如:
QPushButton#okButton { color: gray }
QPushButton { color: red }
两者都可匹配名为okButton的QPushButton实例,但是两者存在冲突。为了解决这个冲突,我们需要考虑选择器的指定。在上述例子中,QPushButton#okButton被认为是更合适的。因为它引用了单一的对象,而不是类的所有实例。
相似的,带有伪状态的选择器也优先于未指定伪状态的选择器。
一个有趣的例子:
QPushButton:hover { color: white }
QPushButton:enabled { color: red }
两个选择器都指定了伪状态,所以如果当按钮使能时,鼠标经过按钮,第二个规则有效。如果我们希望此时文字为白色,我们应该重新设置规则:
QPushButton:enabled { color: red }
QPushButton:hover { color: white }
对于基类和继承类,优先使用继承类的规则。
级联
样式表可以用于QApplication,父窗体,子窗体等。一个任意的窗体的效果样式表都可以通过合并窗体的祖先窗体的样式表集来得到。
当发生解析冲突时,窗体自身的样式表将优先于继承的样式表。
可以得出结论:为窗体设置一个样式表将自动地覆盖它继承自祖先类的样式表。
继承
在传统的CSS中,当窗体的字体和颜色没有明确设定时,将自动继承父窗体的字体和颜色。当使用Qt样式表时,窗体将不会自动继承父窗体的字体和颜色。
例如:
考虑一个QGroupBox中的QPushButton。
qApp->setStyleSheet(“QGroupBox { color: red; }”);
QPushButton没有明确的颜色集,它将使用系统默认颜色,而不是继承它的父窗体QGroupBox的颜色。如果我们希望设置颜色也与QGroupBox和它的子窗体,我们可以如下设计:
qApp->setStyleSheet(“QGroupBox, QGroupBox * { color: red;}”);
在C++命名空间中的窗体
用于为特定类型的窗体设置样式的类型选择器。例如:
class MyPushButton : public QPushButton {
//...
}
//...
qApp->setStyleSheet(“MyPushButton { background: yellow}”);
Qt样式表使用窗体的Object::className()来判断何时使用类型选择器。当自定义窗体位于命名空间中时,QObject::className()返回<namespace>::<classname>。这将产生子控件的语法冲突。为解决该问题,当将类型选择器用于命名空间中的窗体时,我们必须使用”--”代替”::”。
例如:
namespace ns{
class MyPushButton : public QPushButton {
//...
}
}
//...
qApp->setStyleSheet(“ns--MyPushButton { background: yellow;}”);
Qt Designer集成
Qt Designer是一个很好的工具来展示样式表。你可以在任何窗体上使用右键点击选择Change styleSheet来设置样式表。
使用样式表自定义Qt窗体
当使用样式表时,每个窗体都被作为含有4个直角矩形的盒子。由外至内的顺序为:边缘矩形(margin rectangle),边界矩形(border rectangle),填充矩形(padding rectangle),内容矩形(content rectangle)。
margin,border-width,padding属性默认都为0。在这种情况下,所有的4个矩形大小一样。
你可以使用background-image属性为窗体指定一个背景。默认情况下,北京图片仅被绘制在border内部的区域。可以通过使用background-clip属性进行更改。可以使用background-repeat和background-origin来控制背景图片的重复方式和定位方式。
background-image不会随着窗体尺寸进行缩放。为了提供一个可以随窗体尺寸缩放的背景,必须使用border-image。由于border-image属性提供可选的背景,当指定了border-image时,它不要求指定background-image。当两者都指定时,border-image在background-image之上进行绘制。
此外,iamge属性可以被用于在board-image的上层绘制图像。该图像不会平铺或者拉伸。当它的尺寸无法使用窗体时,将使用image-position属性进行设置它的布局。与background-image和board-image不同,它必须使用SVG图像,SVG图像可以根据窗体大小进行自动缩放。
设置规则的步骤如下:
设置修剪圆角以用于全局的渲染操作;(boarder-radius)
绘制背景;(background-image)
绘制边界;(border-image,border)
绘制顶层图像。(image)
Qt样式表参考手册参阅【Qt帮助->Qt Style Sheets Reference】。