Я пытаюсь создать интерактивный виджет QML, который будет обновлять свою модель.
Прямое изменение модели не работает, поэтому я создаю сигнал updateModel(int index, real x, real y)
в InteractiveGraph
. Однако изменение, сделанное в onUpdateModel
, не влияет на пользовательский интерфейс.
Я также пытался использовать обработчик onUpdateModel
, например, такой: { var newModel = model.slice(); newModel[index].x = x; newModel[index].y = y; model = newModel }
, но результат еще хуже, поскольку он нарушает самотаскивание элемента вершины, и модель все равно не обновляется в пользовательском интерфейсе.
Разве класс Array
не является хорошей моделью для этого варианта использования? Есть какая-нибудь готовая модель, которая более подходит?
InteractiveGraph.qml :
import QtQuick 2.0
/* An interactive undirected graph, whose vertices are draggable */
Item {
id: root
property alias model: repeater.model
property real size: 20
signal updateModel(int index, real x, real y)
Canvas { // render lines connecting the vertices
anchors.fill: parent
onPaint: {
var ctx = getContext("2d")
ctx.beginPath()
for(var i = 0; i < model.length; i++) {
if(i === 0) ctx.moveTo(model[i].x, model[i].y);
else ctx.lineTo(model[i].x, model[i].y);
}
ctx.closePath()
ctx.stroke()
}
}
Repeater { // instantiate items corresponding to vertices
id: repeater
delegate: Rectangle {
id: self
color: "red"
border.color: "#000"
width: size
height: size
x: modelData.x - size/2
y: modelData.y - size/2
Text { anchors.centerIn: parent; text: index }
MouseArea { // make items self-draggable
anchors.fill: parent
drag.target: self
}
// invert the x and y relation, and send back the change to model
onXChanged: root.updateModel(index, x + size/2, y + size/2)
onYChanged: root.updateModel(index, x + size/2, y + size/2)
}
}
}
main.qml :
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
id: root
visible: true
width: 640
height: 480
title: qsTr("Hello World")
InteractiveGraph {
id: interactiveGraph
anchors.fill: parent
model: [
{x: 15, y: 20},
{x: 100, y: 220},
{x: 145, y: 230},
{x: 225, y: 130},
{x: 140, y: 88},
{x: 290, y: 60},
]
onUpdateModel: { model[index].x = x; model[index].y = y; model = model; }
}
}