Technical concept

Overview

Skin System

The skin system is designed to support switching the current skin of a widget at run-time. The steps required to include a skin into the build system are described in the section Build System. Every widget that is skinnable has a defined set of graphics. For instance, QtSvgButton uses the graphics named hovered, pressed and normal.

Each skin has a unique name like e.g. Beryl. This skin name must be used in the source code to set a skin. The advantage of setting a skin for every widget explicitely is to support different skins simultaneously. For example, an application can have two instances of a QtSvgButton, one displayed in the skin Beryl and the other in skin BerylSquare. This way the skin is easily extensible by just adding new graphics and bundling them in one Qt resource file.

A Qt resource file is an archive that includes several files. The files then can be accessed in all Qt classes when prefixed with a colon (read more about Qt's Resource System for further information). The skin system requires that the graphics are available as Scalable Vector Graphics (SVG) files.

The widget implementations use QSvgRenderer to load and render SVG files. It is worth to note that QSvgRenderer supports all static features of SVG tiny 1.2 (see also the Qt SVG module).

The folder structure of a resource file always looks similar to the one in QtSvgToggleSwitch, filename beryl_svgtoggleswitch.qrc:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file>svgtoggleswitch/Beryl/on.svg</file>
    <file>svgtoggleswitch/Beryl/off.svg</file>
</qresource>
</RCC>

The general naming spec looks like this:

<widget-name>/<skin-name>/<file-name>.svg

Skins can be created with the following steps # create a Qt resource file, e.g. beryl_svgtoggleswitch.qrc with similar content as shown above # creating the svg graphic files in the correct folder structure and SVG file name. The file names are described in the widget sections below.

Build System

All skins are available in the folder skins. Details about the skin system can be found in the section Skin System.

The widgets themselves are available in the folder src. An example of how to integrate the widgets can be found in the folder examples. There are two projects, Catalog and PatientCare. The widgets are included in the qmake files (.pro files) which is shown in this examaple:

# include pri file with source code
include(../../src/5waybutton/5waybutton.pri)

# add resource file with SVG graphics
RESOURCES += ../../skins/beryl_5waybutton.qrc

Now the project includes the needed files to use Qt5WayButton in the code:

#include <Qt5WayButton>

// later in the code
Qt5WayButton* button = new Qt5WayButton(this);
button->setSkin("Beryl");

Widgets

The following sections describe the concepts and implementation of buttons, gauges, sliders and advanced widgets in detail.

Buttons

All buttons derive from the abstract base class QAbstractButton. This way they share a common Qt style API and behave similar to QPushButton for instance. The following sections present each button.

QtSvgSlideSwitch

svgslideswitch.png

QtSvgSlideSwitch (Beryl skin)

QtSvgSlideSwitch is a SVG based button. Its appearance can be changed with QtSvgSlideSwitch::setSkin(). It reimplements the pure virtual function paintEvent() to draw the content depending on the current button state such as hovered and checked flags.

The following SVG files are required to create a new skin:

QtSvgButton

svgbutton.png

QtSvgButton (Beryl skin)

QtSvgButton is a SVG based button. Its appearance can be changed with QtSvgButton::setSkin(). It reimplements the pure virtual function paintEvent() to draw the current state of the button which is one of normal, hovered or pressed state.

The following SVG files are required to create a new skin:

QtSvgToggleSwitch

svgtoggleswitch.png

QtSvgToggleSwitch (Beryl skin)

QtSvgToggleSwitch is a SVG based button and very similar to QtSvgButton. Its appearance can be changed with QtSvgButton::setSkin(). QtSvgToggleSwitch reimplements the pure virtual function paintEvent() to draw the current state of the button which is either checked or unchecked.

The following SVG files are required to create a new skin:

Gauges

The gauges are designed as read-only widgets, i.e. they do not support user input and only display a value. That's why the base class is QWidget.

QtSvgDialGauge

svgdialgauge.png

QtSvgDialGauge (Amperemeter skin)

QtSvgDialGauge is a SVG based widget. It's appearance is basically a static image with a movable needle, for instance like a tachometer in cars. As the center of the needle varies depending on the skin the widget user first has to set the needle center in procentual values (0...1) by calling QtSvgDialGauge::setNeedleOrigin().

The needle rotation depends on the current value and on the minimum and maximum angles. The angle range has to be set by the widget user, as it is different for every skin. The rotation itself is implemented by using Qt's transformation system.

The following SVG files are required to create a new skin:

QtBasicDialGauge

basicdialgauge.png

QtBasicDialGauge (QPainter based)

QtBasicDialGauge is an example of how to create a widget by using Qt's painting engine. It uses QPainter to draw the display without the need for SVG graphics. As the widget is very simple it can be visualized by two drawing operations: # draw the arc # draw the needle depending on the value

This widget does not provide the function setSkin() as it does not use graphics nor does it provide the capability to change the appearance. To support different backgrounds the paintEvent() implementation first class QWidget::paintEvent() and then draws its content.

Sliders

All sliders in Qt usually derive from QAbstractSlider. This base class provides a common API for slider widgets. That is why the following widgets either inherid QAbstractSlider or use QSlider directly.

QtScrollWheel

scrollwheel.png

QtScrollWheel (Beryl skin)

QtScrollWheel is a SVG based widget. As such the widget user has to set a skin by calling QtScrollWheel::setSkin(). For visualization QtScrollWheel reimplements the paintEvent() to display the current state of the wheel. The implementation creates a turn effect to give feedback to the user when the mouse is being moved.

For this, the following graphics are needed in a skin:

QSlider with Qt Style Sheets

cssslider.png

QSlider (Style Sheet based)

QSlider is a slider widget provided by Qt itself. This example shows how to change the appearance by using Qt's Style Sheet system (CSS).

The following style sheet makes a QSlider appear in the Beryl skin:

QSlider::groove:vertical {
    border: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #B1B1B1, stop:1 #000000);
}
QSlider::handle:vertical {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #DFDFDF, stop: 0.5 #7E7E7E, stop:1 #BCBCBC);
    border: 2px solid #709E10;
    border-radius: 3px;
    width: 30px;
    height: 30px;
}
QSlider::add-page:vertical {
    background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop: 0 #C3E0CC, stop: 0.5 #7FB605, stop:1 #D8F000);
}
QSlider::sub-page:vertical {
    background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop: 0 #CCD5CC, stop: 0.5 #435A12, stop:1 #5C6700);
}
QSlider::handle:pressed {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #DFDFDF, stop: 0.5 #7E7E7E, stop:1 #BCBCBC);
    border: 2px solid #D0F201;
    border-radius: 3px;
}

For further details, read the Qt documentation about using Qt Style Sheets.

Advanced Widgets

Qt5WayButton

5waybutton.png

Qt5WayButton (Beryl skin)

The Qt5WayButton is a custom widget composed of five push buttons. All buttons are rendered from SVG files. Internally the buttons are derived from QAbstractButton and layouted in a QGridLayout with 2 rows and 2 columns. This can be visualized as follows:

5waybutton-layout.png

Layout of Qt5WayButton: QGridLayout of size 2x2

Four buttons (left, top, right, bottom) span two cells and the center button spans all four cells.

The five buttons create a widget mask from the SVG graphics and set it with QWidget::setMask(). This way mouse events (click and move) are only accepted when when the mouse is over graphics.

The following SVG files are required to create a new skin:

QtMultiSlider

multislider.png

QtMultiSlider (Beryl skin)

QtMultiSlider is a SVG based progress bar with range slider. Its appearance can be changed with QtMultiSlider::setSkin(). The QtMultiSlider is a vertical progress bar with a minimum and maximum value. An allowed range can be set with the upper and the lower slider. For visualization of the progress bar the QtMultiSlider reimplements the paintEvent() to display the current value in the valuebar.

If the range exceeds the upper slider the signal maximumExceeded() is send. If the range exceeds the lower slider the signal minimumExceeded() is send.

The following SVG files are required to create a new skin:

QtScrollDial

scrolldial.png

QtScrollDial (Beryl skin)

scrolldial-advanced.png

QtScrollDial with interaction (Beryl skin)

QtScrollDial is a SVG based dial. Its appearance can be changed with QtScrollDial::setSkin(). The scrolldial has two different states. The first image shows the current value. The second image shows the popup window with which the current value can be changed. The new value is accepted when the popup window is closed.

The following SVG files are required to create a new skin:

QtBasicGraph

basicgraph.png

QtBasicGraph

QtBasicGraph is a widget that shows a plot. The widget inherits from QAbstractItemView. For visualization QtBasicGraph reimplements the paintEvent() to display the current plot.

A QStandardItemModel with two colums and arbitray rows is used as the data source. The first column is the x value and the second column the y value.

The visible data area in the widget can be changed by subclassing QtRangeHandler. With a new implementation of the QtRangeHandler it is possible to define the visible area depending on the given model.

An example implementation of the QtRangeHandler is the FixedRangeHandler.

Because of the inhertance of QAbstractItemView some functions have to be implemented but actually not needed.

These are
visualRect(), scrollTo(), indexAt(), moveCursor(), horizontalOffset(), verticalOffset(), isIndexHidden(), setSelection(), visualRegionForSelection(), setRangeHandler()


Generated on Wed Nov 25 17:57:34 2009 for Embedded Widgets by  doxygen 1.6.1