Search code examples
qtanimationwindowqmlqtquick2

QML animation - moving the application window


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?


Solution

  • 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()
        }
    }