三角形を描画し、Shape {}を使用して三角形を削除できるウィンドウを作成しようとしています。以下の例では、2種類の三角形を描くことができます。
基本的に、三角形のタイプを選択し(右下隅にボタンがあります)、ウィンドウの任意の場所をクリックして三角形を取得します。
クリックすると、三角形が動的に作成され、プロパティtriangleListに保存されます。次に、関数shape.update()を呼び出して、shapeのデータプロパティを更新します。この部分はうまく機能します。
ここで、Shapeで使用する関数の更新(データはリストであるため、新しいリストに再割り当てする必要があります):
function update()
{
data = [];
var d = [];
for (var i = 0; i < canvas.triangleList.length; i++)
{
d.push( canvas.triangleList[i] );
}
data = d;
}
三角形を削除しようとすると問題が発生します。私の例では、最初、最後、またはすべての三角形を削除できます。私は三角形を削除すると、最初に私はで値を削除triangleListその後、私は再び呼び出す)(shape.update。すべての三角形または最後の三角形を削除すると機能します。
ただし、最初の三角形を削除しようとすると、新しいリストを指定してもデータはオブジェクトを更新しません。実際、それは常に最後の三角形を削除します。例の下:
dataプロパティは、三角形が1つ少ないことを認識しますが、他の三角形は更新しません。私が見つけた唯一の解決策は、プロパティを変更してから元の値に戻すことです。このようにして、データを強制的に更新します。しかし、私は異なる可能性のあるすべてのプロパティ(色と位置)に対してそれを行う必要があります。したがって、私のupdate()関数は次のようになります。
for (var i = 0; i < canvas.triangleList.length; i++)
{
d.push( canvas.triangleList[i] );
////// Change properties one by one to force the refresh
// Force path redraw. Otherwise only the last path can be deleted
d[i].startX++;d[i].startX--;
// Force line color update
d[i].strokeColor = "red"
d[i].strokeColor = d[i].isUp ? "green" : "yellow";
// Force fill color update
d[i].fillColor = "red";
d[i].fillColor = d[i].isUp ? "green" : "transparent";
data = d;
}
違いを確認するために、これらの行にコメントイン/コメントアウトすることをお勧めします。このトリックを使用して強制的に更新することもできますが、実際のコードはこの例よりも実際に大きく、バインディングを使用しています。
だから私の質問は:各プロパティを変更せずに更新を強制する方法はありますか?
テストする場合の完全なコードは次のとおりです。
import QtQuick 2.9;
import QtQuick.Controls 2.2;
import QtQuick.Shapes 1.0;
ApplicationWindow {
visible: true; width: 640; height: 480;
Rectangle {
id: canvas;
anchors.fill: parent;
color: "black";
property var triangleList: [];
property bool triangleUp: true;
MouseArea {
anchors.fill: parent;
onClicked: {
var triangle = componentTriangle.createObject(componentTriangle, {
"isUp" : canvas.triangleUp,
"startX" : mouse.x,
"startY" : mouse.y,
}, canvas);
canvas.triangleList.push(triangle);
shape.update();
}
} // MouseArea
Shape {
id: shape;
anchors.fill: parent;
function update()
{
data = [];
var d = [];
for (var i = 0; i < canvas.triangleList.length; i++)
{
d.push( canvas.triangleList[i] );
///////////// HOW TO AVOID THE PART BELOW? /////////////
////// Change properties one by one to force the refresh
// Force path redraw. Otherwise only the last path can be deleted
d[i].startX++;d[i].startX--;
// Force line color update
d[i].strokeColor = "red"
d[i].strokeColor = d[i].isUp ? "green" : "yellow";
// Force fill color update
d[i].fillColor = "red";
d[i].fillColor = d[i].isUp ? "green" : "transparent";
//////////////////////////////////////////////////////
}
data = d;
// I make sure data has at least one path to ensure the refresh
if (data.length == 0)
data.push(Qt.createQmlObject('import QtQuick 2.9; import QtQuick.Shapes 1.0; ShapePath {startX:0;startY:0;}', canvas,
"force_refresh"));
}
} // Shape
} // Rectangle
//////////// Buttons to handle the triangles
Column {
anchors.bottom: parent.bottom;
anchors.right: parent.right;
Button {
text: canvas.triangleUp? "Draw triangleUp" : "Draw triangleDown";
onClicked: { canvas.triangleUp = !canvas.triangleUp; }
} // Button
Button {
text: "Clear first";
onClicked: {
canvas.triangleList[0].destroy();
canvas.triangleList.splice(0,1);
shape.update();
}
} // Button
Button {
text: "Clear last";
onClicked: {
canvas.triangleList[canvas.triangleList.length -1].destroy();
canvas.triangleList.splice(canvas.triangleList.length -1,1);
shape.update();
}
} // Button
Button {
text: "Clear all";
onClicked: {
for (var i = 0; i < canvas.triangleList.length; i++)
canvas.triangleList[i].destroy();
canvas.triangleList = [];
shape.update();
}
} // Button
}
//////////// Component to draw the triangle
Component {
id: componentTriangle;
ShapePath {
property bool isUp;
property real offsetX: isUp? -20 : 20;
property real offsetY: isUp? -30 : 30;
strokeColor: isUp ? "green" : "yellow";
strokeWidth: 3;
fillColor: isUp ? "green" : "transparent";
PathLine { x: startX - offsetX; y: startY - offsetY }
PathLine { x: startX + offsetX; y: startY - offsetY }
PathLine { x: startX; y: startY }
} // ShapePath
}
}
ご協力いただきありがとうございます。不明な点がございましたら、お気軽にお問い合わせください。
ごきげんよう!
多くのアイテム(形状)を処理する場合は、モデルでリピーターを使用することをお勧めします。リピーターは、モデルの情報に基づいてアイテムを表示し、モデルからアイテムを削除するだけでアイテムを削除する責任があります。
main.qml
import QtQuick 2.9;
import QtQuick.Controls 2.2;
import QtQuick.Shapes 1.0;
ApplicationWindow {
visible: true; width: 640; height: 480;
QtObject{
id: internals
property bool triangleUp: true;
}
ListModel{
id: datamodel
}
Rectangle {
id: canvas;
anchors.fill: parent;
color: "black";
Repeater{
model: datamodel
Triangle{
x: model.x
y: model.y
isUp: model.isUp
}
}
MouseArea{
anchors.fill: parent
onClicked: datamodel.append({"x": mouse.x, "y": mouse.y, "isUp": internals.triangleUp})
}
}
Column {
anchors.bottom: parent.bottom;
anchors.right: parent.right;
Button {
text: internals.triangleUp ? "Draw triangleUp" : "Draw triangleDown";
onClicked: internals.triangleUp = !internals.triangleUp;
} // Button
Button {
text: "Clear first";
onClicked: if(datamodel.count > 0) datamodel.remove(0)
} // Button
Button {
text: "Clear last";
onClicked: if(datamodel.count > 0) datamodel.remove(datamodel.count - 1)
} // Button
Button {
text: "Clear all";
onClicked: datamodel.clear()
} // Button
}
}
Triangle.qml
import QtQuick 2.9;
import QtQuick.Shapes 1.0
Shape {
id: shape
property bool isUp: false
QtObject{
id: internals
property real offsetX: isUp? -20 : 20;
property real offsetY: isUp? -30 : 30;
}
ShapePath {
strokeWidth: 3;
strokeColor: isUp ? "green" : "yellow";
fillColor: isUp ? "green" : "transparent";
PathLine { x: -internals.offsetX ; y: -internals.offsetY }
PathLine { x: internals.offsetX; y: -internals.offsetY }
PathLine { x: 0; y: 0 }
}
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加