diff options
author | Mitch Curtis <mitch.curtis@theqtcompany.com> | 2016-04-22 10:13:12 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2016-04-26 14:48:09 +0000 |
commit | 3393180efbb186bee365deb730afa42e670a3187 (patch) | |
tree | c2a85b4fed00f0c27ba22ec5729429c360714e87 /src/imports/controls/doc/src | |
parent | 3d23801a874efff4821b7ee17f6ec098e22cf97a (diff) |
Document how to create custom styles
Change-Id: I8abdb2133e1ff66b317e93fa65ff1faa5266410b
Task-number: QTBUG-51785
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
Diffstat (limited to 'src/imports/controls/doc/src')
-rw-r--r-- | src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc index f327c302..5b877736 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc @@ -34,6 +34,300 @@ provide a custom look and feel, the default QML implementation of each item can be replaced with a custom one. + \section1 Customizing a Control + + Sometimes you'll want to create a "one-off" look for a specific part of + your UI, and use a complete style everywhere else. Perhaps you're happy + with the style you're using, but there's a certain button that has some + special significance. + + The first way to create this button is to simply define it in-place, + wherever it is needed. For example, perhaps you're not satisfied with the + default style's Button having square corners. To make them rounded, you + can override the \l {Control::}{background} item and set the radius + property of Rectangle: + + \qml + import QtQuick 2.6 + import QtQuick.Controls 2.0 + + ApplicationWindow { + width: 400 + height: 400 + visible: true + + Button { + id: button + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: button.down ? "#d6d6d6" : "#f6f6f6" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + } + \endqml + + The second way to create the button is good if you plan to use your rounded + button in several places. It involves moving the code into its own QML file + within your project. + + For this approach, we'll copy the background code from the default style's + \c Button.qml. This file can be found in the following path in your Qt + installation: + + \c {$QTDIR/qml/QtQuick/Controls.2/Button.qml} + + After doing that, we'll simply add the following line: + + \qml + radius: 4 + \endqml + + To avoid confusion with the controls in the + module itself, we'll call the file \c MyButton.qml. To use the control in + your application, refer to it by its filename: + + \qml + import QtQuick.Controls 2.0 + + ApplicationWindow { + MyButton { + text: qsTr("A Special Button") + } + } + \endqml + + The third way to create the button is a bit more structured, both in terms + of where the file sits in the file system and how it is used in QML. First, + copy an existing file as you did above, but this time, put it into a + subfolder in your project named (for example) \c controls. To use the + control, first import the folder into a namespace: + + \qml + import QtQuick.Controls 2.0 + import "controls" as MyControls + + ApplicationWindow { + MyControls.Button { + text: qsTr("A Special Button") + } + } + \endqml + + As you now have the \c MyControls namespace, you can name the controls after + their actual counterparts in the Qt Quick Controls 2 module. You can repeat + this process for any control that you wish to add. + + \section1 Creating a Custom Style + + There are several ways to go about creating your own styles. Below, we'll + explain the various approaches. + + \section2 Definition of a Style + + In Qt Quick Controls 2, a style is essentially an interchangeable set of + QML files within a single directory. There are two requirements for a style + to be \l {Using Styles in Qt Quick Controls 2}{usable}: + + \list + \li At least one QML file whose name matches a control (for example, + \c Button.qml) must exist. + + The Default style will be used for any controls that aren't implemented. + \li The files must be in a directory in the filesystem or in the + \l {The Qt Resource System}{resource system}. + + For example, these are all valid paths to a style: + + \list + \li \c {./myapp -style /home/absolute/path/to/my/style} + \li \c {./myapp -style :/mystyle} + \li \c {./myapp -style relative/path/to/my/style} + \li \c {./myapp -style MyStyle} + \endlist + + The third and fourth paths will be looked up within the QML engine's import path + list. This is the same as what happens when you pass \c Material as the style, + for example. + \endlist + + What this means is that you can implement as many controls as you like for + your custom style, and place them almost anywhere. It also allows users to + create their own styles for your application. + + \section2 Style-specific C++ Extensions + + Sometimes you may need to use C++ to extend your custom style. There are two + ways to expose such types to QML: + + \list + \li If the style that uses the type is the only style used by an application, + it's enough to register it with the QML engine via qmlRegisterType(): + + \code + qmlRegisterType<ACoolCppItem>("MyApp", 1, 0, "ACoolItem"); + \endcode + + See \l {Using C++ Data From QML} for more information about this. + \li If the style that uses the type is one of many styles used by an + application, it may be better to only register it when necessary. This + is the point at which it would make sense to implement your own + \l {Creating C++ Plugins for QML}{QML plugin}. + + Using a plugin as part of your style is not that much different from + using a set of QML files. The only difference is that the plugin and + its \c qmldir file must be present in the same directory as the QML + files. + \endlist + + \section3 Attached properties + + It is common for a style to have certain properties or attributes that + apply to all controls. \l {Attached Properties and Attached Signal + Handlers}{Attached properties} are a great way of extending an item in QML + without having to modify any existing C++ belonging to that item. For + example, both the \l {Material Style}{Material} and \l {Universal + Style}{Universal} styles have an attached theme property that controls + whether an item and its children will be rendered in a light or dark theme. + + As an example, let's add an attached property that controls elevation. Our + style will illustrate the elevation with a drop shadow; the higher the + elevation, the larger the shadow. + + The first step is to add a C++ type that stores the elevation. Since the + type will be used for every control supported by our style, and because we + may wish to add other attached properties later on, we'll call it + MyStyle. Here is \c MyStyle.h: + + \code + #ifndef MYSTYLE_H + #define MYSTYLE_H + + #include <QObject> + #include <QtQml> + + class MyStyle : public QObject + { + Q_OBJECT + Q_PROPERTY(int elevation READ elevation WRITE setElevation NOTIFY elevationChanged) + + public: + explicit MyStyle(QObject *parent = nullptr); + + static MyStyle *qmlAttachedProperties(QObject *object); + + int elevation() const; + void setElevation(int elevation); + + signals: + void elevationChanged(); + + private: + int m_elevation; + }; + + QML_DECLARE_TYPEINFO(MyStyle, QML_HAS_ATTACHED_PROPERTIES) + + #endif // MYSTYLE_H + \endcode + + \c MyStyle.cpp: + + \code + #include "mystyle.h" + + MyStyle::MyStyle(QObject *parent) : + QObject(parent), + m_elevation(0) + { + } + + MyStyle *MyStyle::qmlAttachedProperties(QObject *object) + { + return new MyStyle(object); + } + + int MyStyle::elevation() const + { + return m_elevation; + } + + void MyStyle::setElevation(int elevation) + { + if (elevation == m_elevation) + return; + + m_elevation = elevation; + emit elevationChanged(); + } + \endcode + + The \c MyStyle type is special in the sense that it shouldn't be + instantiated, but rather used for its attached properties. For that reason, + we register it in the following manner: + + \code + qmlRegisterUncreatableType<MyStyle>("MyStyle", 1, 0, "MyStyle", "MyStyle is an attached property"); + \endcode + + We then copy the existing default Button style, and add the code for a drop + shadow (which was taken from the Material Button style). We modify that + slightly to ensure that we: + + \list + \li Don't bother using the drop shadow when the elevation is \c 0 + \li Change the shadow's color depending on whether or not the button has + focus + \li Make the size of the shadow depend on the elevation + \endlist + + \qml + layer.enabled: control.enabled && control.MyStyle.elevation > 0 + layer.effect: DropShadow { + verticalOffset: 1 + color: control.activeKeyFocus ? "#330066ff" : "#aaaaaa" + samples: control.MyStyle.elevation + spread: 0.5 + } + \endqml + + With that in place, we can try out our new elevation feature: + + \qml + import QtQuick 2.6 + import QtQuick.Controls 2.0 + + import MyStyle 1.0 + + ApplicationWindow { + id: window + width: 400 + height: 400 + visible: true + + Row { + spacing: 20 + anchors.centerIn: parent + + Button { + text: "Button 1" + } + Button { + text: "Button 2" + MyStyle.elevation: 10 + } + } + } + \endqml + + The end result: + + \image qtquickcontrols2-customize-buttons.png + \section1 Customization Reference The following snippets present the default implementations of various |