Proper way to implement zoom/scale in Qt Quick (QML) Flickable

tro picture tro · Nov 9, 2013 · Viewed 9.1k times · Source

I'm using Qt 5.2 beta, Qt Quick 2.1.

I have straight ahead problem with Flickable component.

Here is minimal working code example:

import QtQuick 2.1
import QtQuick.Controls 1.0

ApplicationWindow {
    width: 300
    height: 200

    Rectangle {
        anchors.fill: parent
        color: "green"

        Flickable {
            id: flickArea
            anchors {fill: parent; margins: 10; }
            contentWidth: rect.width;
            contentHeight: rect.height
            Rectangle {
                id: rect
                x: 0; y: 0;
                width: 200; height: 300;
                color: "lightgrey"

                Rectangle {
                    anchors { fill: parent; margins: 10; }
                    color: "red"
                }
            }
        }
    }
    Button {
        anchors.bottom: parent.bottom;
        anchors.horizontalCenter: parent.horizontalCenter;
        text: "Scale flickArea"
        onClicked: { flickArea.scale += 0.2; }
    }
}

When I'm doing scaling, I expect that all child elements will stay visible as it was before and inner area to become bigger.

But instead, child elements move out of Flickable content.

Can someone propose a normal way to avoid this problem without the need for manual recalculation of all offsets?

Thanks.

Answer

tro picture tro · Nov 11, 2013

I got it work as expected this way, but IMO this way is little bit tricky:

import QtQuick 2.1
import QtQuick.Controls 1.0

ApplicationWindow {
    width: 300
    height: 200

    Rectangle {
        anchors.fill: parent
        color: "green"

        Flickable {
            id: flickArea
            anchors {fill: parent; margins: 10; }
            contentWidth: rect.width*rect.scale
            contentHeight: rect.height*rect.scale
            Rectangle {
                id: rect
                transformOrigin: Item.TopLeft
                x: 0; y: 0;
                width: 200; height: 300;
                color: "lightgrey"

                Rectangle {
                    id: inner
                    anchors { fill: parent; margins: 10; }
                    color: "red"
                }
            }
        }
    }
    Button {
        anchors.bottom: parent.bottom;
        anchors.horizontalCenter: parent.horizontalCenter;
        text: "Scale flickArea"
        onClicked: {
            rect.scale += 0.2;
        }
    }
}

Can someone propose something better?

UPD. I did not close this question for 1 year, but still didn't get any better solution or better way to doing things.