3
votes

I want to create an animation to move (or resize) my application Window built using QML.

I have the following code (most of it created by default when we create a QT quick Controls application:

main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

MainForm.ui.qml

import QtQuick 2.6
import QtQuick.Controls 1.5
import QtQuick.Layouts 1.3

Item {
    width: 640
    height: 480

    property alias button1: button1
    property alias button2: button2

    RowLayout {
        anchors.centerIn: parent

        Button {
            id: button1
            text: qsTr("Press Me 1")
        }

        Button {
            id: button2
            text: qsTr("Press Me 2")
        }
    }
}

main.qml

import QtQuick 2.6
import QtQuick.Controls 1.5
import QtQuick.Dialogs 1.2

ApplicationWindow {
    id: mainWindow
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint

    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: console.log("Open action triggered");
            }
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }

    MainForm {
        anchors.fill: parent
        button1.onClicked: Qt.quit();
        button2.onClicked: state = "other";
    }

    transitions: [
        Transition {
            from: "*"
            to: "other"
            NumberAnimation { properties: "x,y"; easing.type: Easing.InOutQuad; duration: 2000 }

        }
    ]

    states: [
        State {
           name: "other"
           PropertyChanges {
               target: mainWindow
               x: x + 200
           }
       }
    ]

    MessageDialog {
        id: messageDialog

        function show(caption) {
            messageDialog.text = caption;
            messageDialog.open();
        }
    }
}

With this code, I was simply trying to move my window 200 pixels to the right. When I try to run it, I get qrc:/main.qml:42 Cannot assign to non-existent property "states". I believe that is weird, because when I start typing "states" and choose to auto-complete, it builds to me the whole structure, so I thought it should exist...

I'm new to QML, and I'm not fully familiar with the several options of animations that exists. This one I've tried based on the example that comes with QT creator (animation.pro - code from transitions).

I believe it should be quite simple, right? Could you help me with this?

2

2 Answers

2
votes

Qt Creator has a feature where you can insert code snippets using certain keywords. You can see which snippets are available by going to Tools > Options > Text Editor > Snippets.

Snippets will show up as red in the auto completion popup, and regular properties (or types, as is the case below) will show up as green:

creator screenshot

So, ApplicationWindow doesn't have a states property. If you're ever in doubt, go to the documentation for the type you're interested in (e.g. http://doc.qt.io/qt-5/qml-qtquick-controls-applicationwindow.html) and click on the link that says "List of all members, including inherited members". This will show you all properties, functions, etc. belonging to that type.


If you want to animate the window's position, you can use a NumberAnimation without using states:

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 1.5

ApplicationWindow {
    id: window
    width: 400
    height: 400
    visible: true

    NumberAnimation {
        id: xyAnimation
        target: window
        properties: "x,y"
        easing.type: Easing.InOutQuad
        duration: 2000
        to: 500
    }

    Button {
        text: "Start"
        onClicked: xyAnimation.start()
    }
}
2
votes

state is a property in Item, however ApplicationWindow is not an Item. To add state/transition to an non-Item type, use StateGroup:

ApplicationWindow {
    id: mainWindow
    //your code...

    MainForm {
        button2.onClicked: { myWindowStates.state = "other";}
    }

    StateGroup {
        id: myWindowStates

        transitions: [
            Transition {
                from: "*"; to: "other"
                NumberAnimation { 
                    properties: "x,y"; easing.type: Easing.Linear; 
                    duration: 2000 
                }
            }
        ]

        states: [
            State {
               name: "other"
               PropertyChanges {
                   target: mainWindow
                   x: mainWindow.x + 200
                   explicit: true //Remember to set this
               }
           }
        ]
    }
}

Remember to set PropertyChange.explict to true, otherwise the state behavior is wrong and your window will disappear after the transition finished.