Custom Looks Using Qt 4.2 Style Sheets

Материал из Wiki.crossplatform.ru

Версия от 07:56, 10 декабря 2008; Root (Обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

__NOTOC__

by Girish Ramakrishnan

With the introduction of Qt Style Sheets, styling Qt widgets hasbecome a lot simpler. Whether you just need to customizethe look of an existing widget or design a whole new style fromscratch, there is now an alternative to subclassing QStyle.

Содержание

What are Qt Style Sheets?

Qt Style Sheets are heavily inspired by HTML Cascading Style Sheets(CSS) but adapted to widgets. You can set a style sheet on anindividual child widget, on a whole window, or even on a wholeapplication by calling QWidget::setStyleSheet() orQApplication::setStyleSheet().

Under the hood, style sheets are implemented by a special QStyle subclass called QStyleSheetStyle that acts as awrapper for the platform-specific style. This special style appliesany customizations specified using style sheets on top of theunderlying platform-specific style.

Qt 4.2 includes a stylesheet example that lets you experimentwith style sheets. It comes with two styles, Coffee andPagefold.

center

The Coffee style shown above customizes the lookof push buttons, frames, labels, and tooltips, but lets theunderlying style (e.g., Windows XP) draw checkboxes, comboboxes, andradio buttons.

center

In contrast, Pagefold fully redefines the look of all controls usedin the dialog, resulting in a distinctive, platform-independent look.

This article is meant to be a quick introduction to style sheets. Fora complete description of the Qt Style Sheet syntax, please refer tothe online documentation or try out thestylesheet example, located in Qt 4.2's examples/widgetsdirectory.

Basic Style Sheet Syntax

The Qt Style Sheet syntactic rules are almost the same as those ofCSS. If you already know CSS, you can probably skip to the nextsection.

A style sheet consists of a sequence of style rules. Each rule hasthe form

selector { attribute: value }

The "selector" part is typically a class name (e.g., QComboBox), but other syntaxes are possible. The "attribute"part is the name of a style sheet attribute, and "value" is thevalue that is assigned to the attribute.

For convenience, we can use the shorthand notation

selector1, selector2, ..., selectorM {
    attribute1: value1;
    attribute2: value2;
    ...
    attributeN: valueN;
}

which simultaneously sets N attributes on any widget that matchesany of the M selectors. For example,

QCheckBox, QComboBox, QSpinBox {
    color: red;
    background-color: white;
    font: bold;
}

sets the foreground and background colors and the fonts of all QCheckBoxes, QComboBoxes, and QSpinBoxes.

The online documentation lists the supported attributes for eachwidget type. In this article, we will concentrate on the most commonattributes.

The Box Model

When using style sheets, every widget is treated as a box with fourconcentric rectangles: the margin rectangle, the border rectangle,the padding rectangle, and the content rectangle. For a plainwidget &emdash; i.e., a widget with a 0-pixel margins, a 0-pixel thickborder, and 0 pixels of padding &emdash; these four rectangles coincideexactly.

center

The margin area is outside the border and is always transparent. Theborder provides a frame for the widget. Several built-in framestyles, including inset, outset, solid, and ridge,are available by setting the border-style attribute. The paddingprovides spacing between the border and the content area.

Foregrounds and Backgrounds

The foreground color (the color used for drawing text) of the widgetis specified using the color attribute. The background color,specified using background-color, fills the padding rectangle ofthe widget.

The background image, specified using background-image, is drawnin the rectangular area (margin, border, content or paddingrectangle) specified by background-origin. The alignment andtiling of the background image within the rectangular area ismodified using the background-position and background-repeatattribute respectively.

If we specify a background image with an alpha channel (forsemi-transparency), the color specified using background-colorwill shine through. This can be used to reuse the same backgroundimage in a variety of contexts.

center

The following example illustrates the usage of the attributes seen sofar:

QFrame {
    margin: 10px;
    border: 2px solid green;
    padding: 20px;
 
    background-color: gray;
    background-image: url(qt.png);
    background-position: top right;
    background-origin: content;
    background-repeat: none;
}

In this example, the specified margin, border, and padding applyuniformly to all four sides of all QFrames in theapplication.The margin attribute can be used to specify different top, right,bottom, and left values if we want:

QFrame {
    margin: 14px 18px 20px 18px;
}

Alternatively, we can use the margin-top, margin-right,margin-bottom, and margin-left attributes:

QFrame {
    margin-top: 14px;
    margin-right: 18px;
    margin-bottom: 20px;
    margin-left: 18px;
}

Although we have used QFrame in the examples above,we could have specified any Qt widget that supports the box model, including QCheckBox, QLabel, QLineEdit, QListView, QMenu, QPushButton, QTextEdit, and QToolTip.

Creating Scalable Styles

By default, background images specified using background-imageare repeated as many times as necessary, both horizontally andvertically, to cover the widget's padding rectangle (i.e., the areainside the border). If we want to create backgrounds that scalenicely depending on the widget's size, we need to specify a so-called"border image".

Border images are specified using the border-image attribute.They provide both the border and the background of the widget. Aborder image is cut into nine cells, a bit like a tic-tac-toe board:

center

When filling the border of a widget, the four corner cells are takenmore or less "as is", whereas the other five cells are eitherstretched or tiled to fill the available space.

When specifying a border image, we must specify the four "cuts"that define the nine cells, in addition to the border image itself.We must also specify whether we want the non-corner cells to bestretched or tiled, and we must set border-width so that itcorresponds to the cuts (to avoid scaling the corners).

center

For example, here's the style sheet necessary to produce the abovepush button (shown at four different sizes):

QPushButton {
    border-width: 4px;
    border-image: url(button.png) 4 4 4 4 stretch stretch;
}

As in the case of a background image, the border image may have analpha channel that blends with the background-color.

Controlling the Size

The min-width and min-height attributes can be used tospecify the minimum width and height of the contents area of awidget. These values affect the minimumSizeHint() of a widget,which will be honored by the layout. For example:

QPushButton {
    min-width: 68px;
    min-height: 28px;
}

If this attribute is not specified, the minimum height is derived fromthe widget's contents and the current style.

Handling Pseudo-States

The look of widgets can be customized for specific user interfacestates by specifying so-called pseudo-states in the style sheet. Forexample, we may prefer to give a push button a sunken look when it ispressed by the user by specifying the :pressed pseudo-state:

QPushButton {
    border: 2px outset green;
    background: gray;
}
 
QPushButton:pressed {
    border-style: inset;
}

Here's the list of available pseudo-states:

Pseudo-State Description
:checked The button widget is checked.
:disabled The widget is disabled.
:enabled The widget is enabled.
:focus The widget has input focus.
:hover The mouse is hovering over the widget.
:indeterminate The checkbox or radiobutton is partially checked.
:off For widgets that can be toggled, this applies towidgets in the "off" state.
:on For widgets that can be toggled, this applies towidgets in the "on" state. This also applies to comboboxes that havetheir list open, and to menu bars that have one of their menus open.
:pressed The widget is being pressed using the mouse.
:unchecked The button widget is unchecked.

Micro Customization using Subcontrols

Many widgets contain embedded elements, sometimes called"subcontrols". The up and down arrows of a spin box are typicalexamples of subcontrols.

Subcontrols can be specified using :: (e.g., QDateTimeEdit::up- button). Styling them is very similar to stylingwidgets. They follow the box model described above (i.e., they canhave a border, a background, etc.) and can be combinedwith pseudo-states (e.g., QSpinBox::up-button:hover).

The table below lists the subcontrols that are available to stylesheet authors:

Subcontrol Description
::down-arrow The down arrow of a combo or spin box.
::down-button The down button of a spin box.
::drop-down The drop-down arrow of a combobox.
::indicator The indicator of a checkbox, a radio button, or a checkable group box.
::item A menu, menu bar, or status bar item.
::menu-indicator The menu indicator of a push button.
::title The title of a group box.
::up-arrow The up arrow of a spin box.
::up-button The up button of a spin box.

Subcontrols may be placed anywhere in the widget box usingsubcontrol-position and subcontrol-origin. The positioning ofthe subcontrol may be further fine tuned using absolute or relativepositioning. The choice of positioning technique depends on whetherthe subcontrol has a fixed size or has a size that is dependent onthe widget's box.

Relative Positioning

Relative positioning is suitable for subcontrols that have a fixed size(specified using the width and height attributes). Using thistechnique, the subcontrol may be moved by an offset from the positionthat was defined using subcontrol-position andsubcontrol-origin. The left attribute may be used to move thesubcontrol to the right and top attribute may be used to move thesubcontrol to the bottom. For example:

QPushButton::menu-indicator {
    image: url(menu_indicator.png);
    width: 13px;
    height: 13px;
 
    subcontrol-origin: padding;
    subcontrol-position: bottom right;
}
center center

When the user presses a button, we can move the menu indicator fromits original position by a few pixels to the bottom right to simulatea button press:

QPushButton::menu-indicator:pressed {
    position: relative;
    top: 2px;
    left: 2px;
}

Absolute Positioning

Absolute positioning is suitable for subcontrols with a size thatdepends on the size of the widget's box. As before,subcontrol-origin is used to define a rectangle of reference inthe widget's box. The rectangular area for the subcontrol is thendefined by providing offsets from the top, right, bottom, and leftedges of this reference rectangle:

QPushButton::menu-indicator {
    border: 2px solid red;
 
    subcontrol-origin: padding;
    position: absolute;
    top: 2px;
    right: 2px;
    bottom: 2px;
    left: 40px;
}

For subcontrols that have a fixed width or a fixed height, thesubcontrol-position maybe used to specify an alignment within thesubcontrol-origin rectangle:

QPushButton::menu-indicator {
    image: url(menu_indicator.png);
    width: 13px;
 
    subcontrol-origin: padding;
    subcontrol-position: bottom right;
    position: relative;
    top: 2px;
    bottom: 2px;
    right: 2px;
}

Copyright © 2007 Trolltech Trademarks