States und Transitions

Nun wollen wir etwas Bewegung in unser Programm bringen dazu verwenden wir die Möglichkeit von Qt Quick States zu erstellen.

Ein State ist ein Zustand bei dem sich Irgend ein vorhandenes Objekt verändert z.B in seiner Größe , Position oder sonstigen Eigenschaften.

Um einen State zu erstellen  gehen wir in den Designer und klicken oben auf das Plus wir erstellen für unser Beispiel 2 zusätzliche States in denen wir unseren Button an eine andere Position setzen.

states

Wir können beliebig viele States erstellen.  Im qml-Code wird eine Liste erstellt die die Einzelnen States und ihre Veränderung anzeigt.

    states: [
        State {
            name: "State1"

            PropertyChanges {
                target: button1
                x: 0
                y: 260
            }
        },
        State {
            name: "State2"
            PropertyChanges {
                target: button1
                x: 260
                y: 260
            }
        }
    ]

Eine Liste ist immer durch die [ ] gekennzeichnet.

So jetzt müssen wir nur noch den Zustand Irgendwie ändern aber wie ?

Wir wollen das bei jedem klick auf den Button in den nächsten Zustand gewechselt wird. Dazu müssen wir eine Variable Index einführen

Variablen heissen in qml property. Diese fügen wir in die geschweiften Klammern von Rectangle zu Beginn ein.

 property int index: 0

Diese Property können wir nun bei jedem klick erhöhen und sie als Indentifikator für unseren Zustand verwenden dazu fügen wir folgenden Code in die onClicked: Eigenschaft des Buttons.

  onClicked:{
                    index++
                    labeltext.text=index

                    if (index>=3)index=0;
                    if (index==0)main_window.state=""
                    if (index==1)main_window.state="State1"
                    if (index==2)main_window.state="State2"

              }

Der Grundzustand wird wieder erreicht durch die „“ was keinem Zustand also dem Normal Zustand entspricht. main_window ist die id unseres Rectangles die wir noch vergeben müssen da wir bis dato keine id dafür haben. Dort wo Hallo World steht wird der aktuelle Index angezeigt. Starten wir nun das Programm können wir die Zustände durch klicken auf unseren Knopf durchschreiten.

Ein bisschen lahm sieht das ganze schon aus daher fügen wir eine Animation hinzu,die in qml Transition genannt wird.

 transitions: Transition {
           NumberAnimation { properties: "x,y"; easing.type: Easing.InBounce }
       }

Hier eine NumberAnimation der x,y Koordinaten unseres Buttons, der easing.type gibt die Bewegung an. Klicken wir mit rechter Maustaste auf das easing.type argument können wir mit Qt Quick Werkzeugleiste anzeigen die gewünschte Bewegungsanimation einstellen. (Dies ist immer möglich wenn eine kleine Glühbirne im Editor erscheint diese erscheint wenn wir z.b unseren Cursor hinter die Number Animation setzen )

qt_quick_tool

Mit der Werkzeugleiste können wir uns die Animation durch klicken auf den Play Pfeil anschauen  und beliebig verändern.

Nun haben wir eine erste Anwendung mit Bewegung hier nochmal der komplette Code wie er bissher bei mir aussieht:

import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0

Rectangle {
    id: main_window
    property int index: 0
    width: 360
    height: 360
    color: "#1e864b"
    radius: 0
    transformOrigin: Item.Center
    Text {
        id: labeltext
        text: qsTr("Hello World")
        opacity: 1
        smooth: true
        anchors.centerIn: parent
    }
    MouseArea {
        id: mousearea1
        x: 0
        y: 0
        anchors.rightMargin: 0
        anchors.bottomMargin: 0
        anchors.leftMargin: 0
        anchors.topMargin: 0
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }

                Button {
                    id: button1
                    x: 130
                    y: 40
                    width: 100
                    height: 100

                    style: ButtonStyle {
                            background: Rectangle {
                                implicitWidth: 100
                                implicitHeight:100
                                border.width: control.activeFocus ? 2 : 1
                                border.color: "green"

                                radius: width/2
                                gradient: Gradient {
                                    GradientStop { position: 0 ; color: control.pressed ? "lightgreen" : "blue" }
                                    GradientStop { position: 1 ; color: control.pressed ? "darkgreen" : "darkblue" }
                                }
                            }
                        }

                    text: "Button"
                    tooltip: "Das ist ein Button"

                    onClicked:{
                                index++
                                labeltext.text=index

                                if (index>=3)index=0;
                                if (index==0)main_window.state=""
                                if (index==1)main_window.state="State1"
                                if (index==2)main_window.state="State2"

                              }

                     //hier wird der Text beim clicken geändert
                }

    }
    states: [
        State {
            name: "State1"

            PropertyChanges {
                target: button1
                x: 0
                y: 260
            }
        },
        State {
            name: "State2"
            PropertyChanges {
                target: button1
                x: 260
                y: 260
            }

        }
    ]

    transitions: Transition {
           NumberAnimation { properties: "x,y"; easing.type: Easing.InBounce }
       }

}

Custom Styles für Qt Quick Controls

Hmm ich möchte meinem Knopf eine andere Farbe und Form geben aber es gibt im QtQD keine Farbauswahl für mein Button Objekt.  Also wie stelle ich das an?

Die Lösung heist:

import QtQuick.Controls.Styles 1.0

hiermit lässt sich der Style in unserem fall der Buttonstyle anpassen.

Dazu müssen wir bei unserem Button folgenden Code einfügen:

 Button {
          id: button1
          x: 130
          y: 38
          width: 100
          height: 100
          style: ButtonStyle 
                {
                 background: Rectangle 
                      {
                        color: control.pressed ? "green" : "blue"  //ist der Knopf gedrückt wenn nein blau wenn ja grün
                        implicitWidth: 100                         //wird keine Größe angegeben werden die impliciten größen verwendet 
                        implicitHeight:100
                        border.width: control.activeFocus ? 2 : 1 //wird mit tab auf activer focus geschaltet verändert sich der Button Rand
                        border.color: "#999"
                        radius: width/2 // die Größe halbiert ergibt einen Runden Button
                      }
                 }
          }

Der Ternary Operator bedeutet folgendes: condition ? true-statement : false-statement

qml_button_style

Schon haben wir einen bunten Knopf der grün wird wenn wir ihn drücken.
Ein bisschen hässlich sieht er ja schon aus unser Knopf um ihn zu verschönern belegen wir ihn mit einem Gradienten

also in die geschweifte Klammer von Style->Rectangle  folgendes einfügen:

  gradient: Gradient {
                        GradientStop { position: 0 ; color: control.pressed ? "lightgreen" : "blue" }
                        GradientStop { position: 1 ; color: control.pressed ? "darkgreen" : "darkblue" }
                     }

Es wird ein Farbübergang von position 0 auf position 1 gemacht (man kann beliebig viele Positionen einfügen) in unserem Fall wenn der Knopf nicht gedrückt ist von blue->darkblue und wenn er gedrückt ist von lightgreen nach darkgreen hier kann man auch jede Beliebige Farbe wählen von #fffff bis #00000. Der Gradient überschreibt die eigenschaft color daher can die Zeile color: control.pressed ? „green“ : „blue“ gelöscht werden

qml_button_style_2

Jetzt schaut unser Knopf schon ansehnlicher aus das Problem  im QtQD wird der Runde Button manchmal nicht sofort angezeigt dort sieht man nach wie vor einen Eckigen Button mit den Standard styles.

Nach einem Neustart vom QtCreator sieht man aber auch hier den runden Entwurf.

Qt Quick Controls unser erster Button

Hallo wir wollen nun einen Button einfügen der z.b unseren Hallo Welt text beim clicken ändert.

Dazu importieren wir in unserem main.qml

import QtQuick.Controls 1.0

Gehen wir dann in unseren QtQD erhalten wir weitere Optionen in unserer QML-Typen auswahl Es gibt diverse controls die wir schon aus der Widget Programmiereung her kennen.

Buttons,Checkboxen Slider…. etc. Wir wählen nun einen Button aus und ziehen ihn auf unser Rectangle.

qml_designer_controls

Diesen Button Können wir Rechts unter Button zusätzlich bearbeiten zb können wir ihn noch mit einem Tooltip versehen oder ein Bild für den Button auswählen.

Starten wir das Programm sehen wir den Button wie gewünsch jedoch wenn wir draufklicken geschieht nichts?

Da wir unseren Hallo Welt Text ändern wollen verpassen wir ihm eine id: damit lässt er sich direkt im qml code ansprechen. Daher ist es wichtig die id’s immer sorgfältig zu wählen damit man später genau weis was sich darunter verbirgt.

Das Label anklicken und oben rechts die ID eintragen:

qml_designer_id

Wir nennen unseren „Hallo Welt“ Text labeltext.

Wir können auch alternativ im Code in die Geschweiften Klammern von Text die id händisch einfügen:

 Text {
        id: labeltext
        text: qsTr("Hello World")
        opacity: 1
        smooth: true
        anchors.centerIn: parent
    }

So jetzt verbinden wir noch den Button mit der Aktion Text ändern mit einem onClicked: 

der ganze Code sieht dann wie folgt aus:

import QtQuick 2.0
import QtQuick.Controls 1.0

Rectangle {
    width: 360
    height: 360
    color: "#1e864b"
    radius: 0
    transformOrigin: Item.Center
    Text {
        id: labeltext
        text: qsTr("Hello World")
        opacity: 1
        smooth: true
        anchors.centerIn: parent
    }
    MouseArea {
        x: 0
        y: 0
        anchors.rightMargin: 0
        anchors.bottomMargin: 0
        anchors.leftMargin: 0
        anchors.topMargin: 0
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }

        Button {
            id: button1
            x: 143
            y: 68
            text: "Button"
            opacity: 1
            scale: 1
            rotation: 0
            onClicked:{labeltext.text="Button Clicked"} //hier wird der Text beim clicken geändert
        }
    }
}

Starten wir nun das Programm wird das label beim drücken des Knopfes geändert.
bei erneutem drücken geschieht jedoch nichts mehr wir können die onClicked: eigenschaft mit einem if statement erweitern so z.B  :

 onClicked:{
                        if (labeltext.text=="Button Clicked")
                        {
                            labeltext.text="Hello World"
                        }
                        else
                        {
                            labeltext.text="Button Clicked"
                        }
                      }

Nun ändert sich der Text bei jedem click.

qml_button_clicked

Möchte man den Button direkt mit C++ Code Verknüpfen ist das etwas komplizierter.

Wir wollen zuerst die Spezialitäten von qml beleuchten und zur Verknüpfung mit C++-Code kommen wir später…