Qt 5.3 QML: создание контейнера элементов больше размера окна

У меня возникла необходимость сделать в приложении, написанном на Qt 5.3 и использующим QML, контейнер элементов интерфейса, который был бы больше окна приложения, то есть какая-то его часть бы была видна пользователю, а все остальное - скрыто в данный момент. Это очень похоже на поведение любого графического редактора при увеличении открытого изображения - становится видна только часть изображения. Соответственно, необходимо также, чтоб была возможность "передвигать" мышкой видимую часть контейнера - при этом в окне должны отображаться скрытые ранее элементы.
В QML для этого есть специальный элемент-контейнер Flickable. Однако в чистом виде его использовать не удалось - поведение не совпадает с ожидаемым. Ниже представлен QML код, который реализует описанное поведение.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import QtQuick 2.0
 
ApplicationWindow {
    visible: true
    id: rootWindow
    width: 640
    height: 480
    title: qsTr("Demo")
 
    Flickable {
        id: flickableContainer
        anchors.fill: parent
        contentWidth: canvasContainer.width
        contentHeight: canvasContainer.height
        //Дополнительный контейнер
        Item {
            id: canvasContainer
            width: canvas.width * canvas.scale
            height: canvas.height * canvas.scale
            //Масштабируемый контейнер, содержащий элементы интерфейса
            Rectangle {
                id: canvas
                color: "WHITE"
                anchors.centerIn: parent
                width: rootWindow.width
                height: rootWindow.height
                //Это нужно, чтоб при масштабировании элемент оставался внутри Flickable
                transformOrigin: Item.TopLeft
                x: 0
                y: 0
                //Для демонстрации изменения масштаба
                MouseArea {
                    anchors.fill: parent
                    acceptedButtons: Qt.LeftButton | Qt.RightButton
                    onClicked: {
                        if (mouse.button == Qt.RightButton)
                            canvas.scale += 0.1
                        else
                            canvas.scale -= 0.1
                    }
                }
                //Пример элемента интерфейса
                Rectangle {
                    width: 50
                    height: 50
                    x: 100
                    y: 100
                    color: "RED"
                    radius: width/2
                }
            }
        }
    }
}
Нужное поведение обеспечивается дополнительным контейнером (у меня это Item cо значением id равным canvasContainer) между элементом Flickable и собственно контейнером с элементами интрефейса (у меня его роль выполняет Rectangle c id canvas). В качестве контейнера элементов интерфейса взят Rectangle a не Item исключительно из-за свойства color - мне нужно выставлять фон контейнера.
Далее в моем примере есть еще MouseArea - ее я добавил для демонстрации изменения масштаба контейнера. По шелчку левой кнопки мыши контейнер уменьшается, по щелчку правой кнопки - увеличивается.
И последний элемент Rectangle, принадлежащий контейнеру, представляет собой пример элемента интерфейса - это просто красный круг. Соответственно, можно посмотреть, как при увеличении контейнера круг в какой-то момент пропадет из видимой зоны в окне приложения, и передвинуть его обратно мышкой.

Комментариев нет :

Отправить комментарий