2017-10-06 1 views
2

Jetzt, während ich meine App auf Qt 5.9 portiere, habe ich ein seltsames Verhalten erlebt. Der Code, um das Problem beschreibt, ist unten:QML unerwartete Bindung

import QtQuick 2.9 
import QtQuick.Window 2.2 
import QtQuick.Controls 2.2 

Window { 
    visible: true 
    width: 600 
    height: 800 
    title: qsTr("Test") 

    Row { 
     id: base 
     property var arr: [] 
     property color currentColor: "red" 
     anchors.centerIn: parent 
     spacing: 5 
     Repeater { 
      model: 10 
      delegate: Rectangle { 
       width: 50 
       height: 50 
       border.width: 1 
       border.color: "grey" 
       color: base.arr[index] === undefined ? "white" : base.arr[index] 
       MouseArea { 
        anchors.fill: parent 
        onClicked: { 
         base.currentColor = Qt.rgba(Math.random(),Math.random(),Math.random(),1); 
         base.arr[index] = base.currentColor; 
         base.arr = base.arr; // trick to fire changing event 
         console.log(base.arr) 
        } 
       } 
      } 
     } 
    } 
} 

So gibt es Reihe von Rechtecken und während einer von ihnen drücken ich gelegentliche Farbe und legen Sie sie in dem Array base.arr irgend Index als Element ein. Es gibt eine Eigenschaft base.currentColor, um die aktuelle Farbe beizubehalten. Aber das Problem ist, dass, wenn ich einem Gegenstand eine neue Farbe zuweise, alle vorherigen Gegenstände auch die Farbe ändern.

Ich denke, das Problem in Linie ist

base.arr[index] = base.currentColor; 

Es sieht aus, dass diese Linie eine unerwartete Bindung oder Referenz erzeugt oder was auch immer ich sehe nicht. Wie ich weiß, ist die einzige Möglichkeit, eine Bindung in Js zu erstellen, Qt.binding, aber hier benutze ich das nicht.

Die Abhilfe dieses Verhalten zu brechen ist so etwas wie dieses:

base.arr[index] = Qt.rgba(base.currentColor.r, base.currentColor.g, base.currentColor.b, base.currentColor.a); 

aber es sieht Overhead- und schmutzige Lösung.

Ich würde mich freuen, wenn jemand dieses seltsame Verhalten erklären kann.

Antwort

1

QML color ist eigentlich eine Farbe object.

In JavaScript-Objekten werden durch Verweis kopiert, so dass eine QML-color-Variable tatsächlich eher wie ein Zeiger verhält.

Auf dieser Linie:

base.arr[index] = base.currentColor; 

das Array-Element wird als eine Referenz zum currentColor Objekt.

Wenn jedes Array-Element festgelegt ist, wird es als Referenz auf dasselbe Objekt currentColor gesetzt! Das Ändern der currentColor ändert also jedes Element in dem Array.

Statt dessen:

property color currentColor: "red" 

Verwendung dieses:

property string currentColor: "red" 

Strings in QML werden immer von Wert kopiert, so dass Sie sich nicht mehr ein Problem.

Voll Code:

import QtQuick 2.9 
import QtQuick.Window 2.2 
import QtQuick.Controls 2.2 

Window { 
    visible: true 
    width: 600 
    height: 800 
    title: qsTr("Test") 

    Row { 
     id: base 
     property var arr: [] 
     property string currentColor: "red" 
     anchors.centerIn: parent 
     spacing: 5 
     Repeater { 
      model: 10 
      delegate: Rectangle { 
       width: 50 
       height: 50 
       border.width: 1 
       border.color: "grey" 
       color: base.arr[index] === undefined ? "white" : base.arr[index] 
       MouseArea { 
        anchors.fill: parent 
        onClicked: { 
         base.currentColor = Qt.rgba(Math.random(),Math.random(),Math.random(),1); 
         base.arr[index] = base.currentColor; 
         base.arr = base.arr; // trick to fire changing event 
         console.log(base.arr) 
        } 
       } 
      } 
     } 
    } 
} 

Was ich nicht verstehen kann, ist - Sie sagten, Sie Ihre App Qt portieren 5.9 ... Wenn Sie von einer früheren Version von Qt portieren, dann bin ich überrascht, dass der Code in der vorherigen Version nicht so war.

+0

Dank @Mark Ch für die Antwort. Alles, was Sie gesagt haben, ist richtig, aber ich mache mir Sorgen wegen eines anderen Problems. Das Zuweisen eines Verweises auf ein Objekt, anstatt dessen Wert zu kopieren, ist hier nicht zu erwarten. Und nach Ihrem Vorschlag verhalten sich einfache Objekte anders? Ein Teil von ihnen weist eine Referenz zu (wie 'color') und ein Teil kopiert seine Werte (wie' string')? – folibis

+0

Ich denke, du bist richtig besorgt, es scheint wie ein Fehler für mich. Ist dieses Verhalten bei Version 5.9 anders als bei früheren Versionen? –

Verwandte Themen