Qt 5.3 QML: как принудительно выполнить перерисовку элемента

Судя по всему, стандартные средства QML не позволяют просто взять и запросить перерисовку заданного объекта. Понятно, что объекты автоматчески перерисовываются при измении их свойств, списки автоматически перерисовываются при изменении привязанных к ним моделей. Но если есть какой-нибудь кастомный элемент интерфейса на основе, например, Rectangle, отрисовка которого зависит от какой-нибудь кастомной модели, проброшенной в QML из С++ кода, все это не поможет. Модель меняется, а вот метода, который бы заставил интерфейс перерисоваться заново с учетом этих изменений, я не нашел.
Единственное решение, которое я нашел, это удалить элемент и пересоздать его заново после изменения модели (как это делать, описано здесь). Правда, статически созданные элементы не рекомендуется удалять динамически, поэтому элементы, которые нужно будет пересоздавать, нужно сразу создавать динамически.

Если взять пример кода из моего предыдущего поста и представить, что нам нужно обновлять упомянутый там canvas (который на самом деле является элементом Rectangle), то код получится примерно следующим:

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
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
        property var canvas: createCanvas();
        //Дополнительный контейнер
        Item {
            id: canvasContainer
            width: canvas.width * canvas.scale
            height: canvas.height * canvas.scale
 
        }
 
        function createCanvas() {
            //Весь код canvas был перенесен в отдеьный файл CustomCanvas.qml
            var canvasComponent = Qt.createComponent("CustomCanvas.qml");
            var canvasObject = canvasComponent.createObject(canvasContainer);
            if (canvasObject === null) {
                console.log("Error creating canvas");
            }
            return canvasObject;
        }
 
        function updateCanvas() {
            var tmp = canvas;
            canvas = createCanvas();
            tmp.destroy();
        }
    }
}

Теперь после изменения данных, на основе которых строится canvas достаточно вызвать функцию: flickableContainer.updateCanvas().

1 комментарий :