QML如何获取Loader的位置
QML how to get the position of Loader
我想生成一个类似流的二叉树来显示与 QML 的组织关系信息。enter image description here
我的方式:
- 像流程示例一样创建树节点。
- 将树节点与 Canvas 对齐,如上图所示。我想得到
在 Loader.onLoaded.
之后点画线
我的问题:
第一步完成后。第二步,获取不到正确的树节点位置点
详情:
根据Qt文档,如果我没有明确设置Loader的宽度和高度,它会自动根据其项目大小设置。但是,我无法获取 Loader.onloaded()
中的节点位置点
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: appWindow
visible: true
width: 1066
height: 600
property var jsonData: [{"id":1,"pid":0},{"id":2,"pid":1},{"id":3,"pid":1},
{"id":4,"pid":2},{"id":5,"pid":2},{"id":6,"pid":3},
{"id":7,"pid":3},{"id":8,"pid":4},{"id":9,"pid":4},{"id":10,"pid":6}]
property int maxRectangles: 5
Component.onCompleted: {
var color = Qt.lighter("red", maxRectangles / 7)
pLoader.sourceComponent = rectangleComponent;
var currItem = pLoader.item;
currItem.color = "blue"
currItem.text = 0
var tmp = {};
tmp[jsonData[0]["id"]] = currItem ;
for(var index = 1; index < jsonData.length; index++) {
color = Qt.lighter("red", index / 7)
var sItem = jsonData[index]["pid"];
if(tmp[sItem].rComponent.sourceComponent === null){
tmp[sItem].rComponent.sourceComponent = rectangleComponent
attachData(tmp[sItem].rComponent.item,index, color);
tmp[jsonData[index]["id"]] = tmp[sItem].rComponent.item ;
}
else {
tmp[sItem].lComponent.sourceComponent = rectangleComponent
attachData(tmp[sItem].lComponent.item,index, color);
tmp[jsonData[index]["id"]] = tmp[sItem].lComponent.item ;
}
}
}
function attachData(item, text, color){
item.text = text;
item.color = color
}
Component {
id: rectangleComponent
Column{
property alias rComponent: rightLoader
property alias lComponent: leftLoader
property alias color: rect.color
property alias text: myText.text
spacing: 40
//anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
id:rect
width: 100
height: 100
Text{
id:myText
font.pixelSize: 18
anchors.centerIn: parent
color:"white"
}
Component.onCompleted: {
console.log("Component.onCompleted", mapToItem(canvas, 0, 0))
}
MouseArea {
anchors.fill: parent
onClicked: {
updateDotPosition(parent)
//here, printed coordinate is my expected
//but i want line them after tree node loaded antomate
console.log("updateDotPosition", mapToItem(canvas, 0, 0))
}
}
}
Row{
spacing: 40
anchors.horizontalCenter: parent.horizontalCenter
Loader {
id:leftLoader
onLoaded: {
console.log("leftLoader", mapToItem(canvas, 0, 0))
}
}
Loader {
id:rightLoader
onLoaded: {
console.log("rightLoader", mapToItem(canvas, 0, 0))
}
}
}
}
}
Canvas{
anchors.fill: parent
id:canvas
Loader {
id:pLoader
anchors.horizontalCenter: parent.horizontalCenter
//sourceComponent: rectangleComponent
}
}
Rectangle {
id: testMapToItemDot
width: 20
height: width
radius: width / 2
z: 1
color: "darkblue"
}
function updateDotPosition(itemToMap) {
var pos = testMapToItemDot.mapFromItem(
itemToMap,
(itemToMap.width - testMapToItemDot.width) / 2, // these parameters are optional - I want to move the dot to
(itemToMap.height - testMapToItemDot.height) / 2) // the center of the object, not upper left corner
testMapToItemDot.x += pos.x
testMapToItemDot.y += pos.y
}
}
加载项的位置和大小可以这样访问:Loader.item.x
、Loader.item.y
、Loader.item.width
、Loader.item.height
.
如果这不是您要查找的内容,请更准确地描述问题。
请查看此示例应用程序。我认为这就是您要找的东西 - 看看 function updateDotPosition(itemToMap)
。请注意,如果您将 "mapping" 指向一个不移动的对象(示例中的点在移动)并且该对象将是具有相同 x
的 Canvas
的同级对象, y
值,然后函数的结果将为您提供精确的点,从哪里画一条线。您将不需要像我一样使用 +=
。
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: appWindow
visible: true
width: 1066
height: 600
property int maxRectangles: 5
Component {
id: rectangleComponent
Rectangle {
x: 110
y: 30
width: 100
height: 100
property var loaderSource
Component.onCompleted: {
color = Qt.lighter("red", maxRectangles / 7)
if (maxRectangles-- > 0)
loaderSource = rectangleComponent
else
loaderSource = undefined
}
Loader {
sourceComponent: loaderSource
}
MouseArea {
anchors.fill: parent
onClicked: {
updateDotPosition(parent)
}
}
}
}
Loader {
sourceComponent: rectangleComponent
}
Rectangle {
id: testMapToItemDot
width: 20
height: width
radius: width / 2
z: 1
color: "darkblue"
}
function updateDotPosition(itemToMap) {
var pos = testMapToItemDot.mapFromItem(
itemToMap,
(itemToMap.width - testMapToItemDot.width) / 2, // these parameters are optional - I want to move the dot to
(itemToMap.height - testMapToItemDot.height) / 2) // the center of the object, not upper left corner
testMapToItemDot.x += pos.x
testMapToItemDot.y += pos.y
}
}
这是您示例的工作版本。这只是一个例子。不幸的是脏了。这是因为我有点难以理解代码中发生的事情——我相信你不会遇到这个问题。我还使用了 Timer
,因为创建时 Rectangle
对象的 x,y
等于 0
。我需要稍等一下。请不要在发布代码中使用它 - 这是糟糕的设计:)
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: appWindow
visible: true
width: 1066
height: 600
property var jsonData: [{"id":1,"pid":0},{"id":2,"pid":1},{"id":3,"pid":1},
{"id":4,"pid":2},{"id":5,"pid":2},{"id":6,"pid":3},
{"id":7,"pid":3},{"id":8,"pid":4},{"id":9,"pid":4},{"id":10,"pid":6}]
property int maxRectangles: 5
Component.onCompleted: {
var color = Qt.lighter("red", maxRectangles / 7)
pLoader.sourceComponent = rectangleComponent;
var currItem = pLoader.item;
currItem.color = "blue"
currItem.text = 0
connectedItems.push([currItem, null])
var tmp = {};
tmp[jsonData[0]["id"]] = currItem ;
for(var index = 1; index < jsonData.length; index++) {
color = Qt.lighter("red", index / 7)
var sItem = jsonData[index]["pid"];
if(tmp[sItem].rComponent.sourceComponent === null){
tmp[sItem].rComponent.sourceComponent = rectangleComponent
attachData(tmp[sItem].rComponent.item,index, color);
tmp[jsonData[index]["id"]] = tmp[sItem].rComponent.item ;
connectedItems.push([tmp[sItem].rComponent.item, null])
}
else {
tmp[sItem].lComponent.sourceComponent = rectangleComponent
attachData(tmp[sItem].lComponent.item,index, color);
tmp[jsonData[index]["id"]] = tmp[sItem].lComponent.item ;
connectedItems.push([tmp[sItem].lComponent.item, null])
}
if ( jsonData[index]["pid"] !== 0) {
connectedItems[connectedItems.length - 1][1] = connectedItems[jsonData[index]["pid"] - 1][0]
}
}
}
function attachData(item, text, color){
item.text = text;
item.color = color
}
property var connectedItems: [];
function paintConnection(objectFrom, objectTo) {
var vectorStart = canvas.mapFromItem(
objectFrom, objectFrom.width / 2, objectFrom.height)
var vectorEnd = canvas.mapFromItem(
objectTo, objectTo.width / 2,0)
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(vectorStart.x, vectorStart.y);
ctx.lineTo(vectorEnd.x,vectorEnd.y);
ctx.stroke();
canvas.requestPaint()
}
Timer {
id: paintLines
interval: 100
running: true
onTriggered: {
for (var i = 1 ; i < connectedItems.length ; i++) {
paintConnection(connectedItems[i][1].rect, connectedItems[i][0].rect)
}
}
}
Component {
id: rectangleComponent
Column{
property alias rComponent: rightLoader
property alias lComponent: leftLoader
property alias color: rect.color
property alias text: myText.text
property alias rect: rect
spacing: 40
//anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
id:rect
width: 100
height: 100
Text{
id:myText
font.pixelSize: 18
anchors.centerIn: parent
color:"white"
}
Component.onCompleted: {
console.log("Component.onCompleted", mapToItem(canvas, 0, 0))
}
MouseArea {
anchors.fill: parent
onClicked: {
updateDotPosition(parent)
//here, printed coordinate is my expected
//but i want line them after tree node loaded antomate
console.log("updateDotPosition", mapToItem(canvas, 0, 0))
}
}
}
Row{
spacing: 40
anchors.horizontalCenter: parent.horizontalCenter
Loader {
id:leftLoader
onLoaded: {
console.log("leftLoader", mapToItem(canvas, 0, 0))
}
}
Loader {
id:rightLoader
onLoaded: {
console.log("rightLoader", mapToItem(canvas, 0, 0))
}
}
}
}
}
Canvas{
anchors.fill: parent
id:canvas
Loader {
id:pLoader
anchors.horizontalCenter: parent.horizontalCenter
//sourceComponent: rectangleComponent
}
}
Rectangle {
id: testMapToItemDot
width: 20
height: width
radius: width / 2
z: 1
color: "darkblue"
}
function updateDotPosition(itemToMap) {
var pos = testMapToItemDot.mapFromItem(
itemToMap,
(itemToMap.width - testMapToItemDot.width) / 2, // these parameters are optional - I want to move the dot to
(itemToMap.height - testMapToItemDot.height) / 2) // the center of the object, not upper left corner
testMapToItemDot.x += pos.x
testMapToItemDot.y += pos.y
}
}
我想生成一个类似流的二叉树来显示与 QML 的组织关系信息。enter image description here
我的方式:
- 像流程示例一样创建树节点。
- 将树节点与 Canvas 对齐,如上图所示。我想得到 在 Loader.onLoaded. 之后点画线
我的问题:
第一步完成后。第二步,获取不到正确的树节点位置点
详情:
根据Qt文档,如果我没有明确设置Loader的宽度和高度,它会自动根据其项目大小设置。但是,我无法获取 Loader.onloaded()
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: appWindow
visible: true
width: 1066
height: 600
property var jsonData: [{"id":1,"pid":0},{"id":2,"pid":1},{"id":3,"pid":1},
{"id":4,"pid":2},{"id":5,"pid":2},{"id":6,"pid":3},
{"id":7,"pid":3},{"id":8,"pid":4},{"id":9,"pid":4},{"id":10,"pid":6}]
property int maxRectangles: 5
Component.onCompleted: {
var color = Qt.lighter("red", maxRectangles / 7)
pLoader.sourceComponent = rectangleComponent;
var currItem = pLoader.item;
currItem.color = "blue"
currItem.text = 0
var tmp = {};
tmp[jsonData[0]["id"]] = currItem ;
for(var index = 1; index < jsonData.length; index++) {
color = Qt.lighter("red", index / 7)
var sItem = jsonData[index]["pid"];
if(tmp[sItem].rComponent.sourceComponent === null){
tmp[sItem].rComponent.sourceComponent = rectangleComponent
attachData(tmp[sItem].rComponent.item,index, color);
tmp[jsonData[index]["id"]] = tmp[sItem].rComponent.item ;
}
else {
tmp[sItem].lComponent.sourceComponent = rectangleComponent
attachData(tmp[sItem].lComponent.item,index, color);
tmp[jsonData[index]["id"]] = tmp[sItem].lComponent.item ;
}
}
}
function attachData(item, text, color){
item.text = text;
item.color = color
}
Component {
id: rectangleComponent
Column{
property alias rComponent: rightLoader
property alias lComponent: leftLoader
property alias color: rect.color
property alias text: myText.text
spacing: 40
//anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
id:rect
width: 100
height: 100
Text{
id:myText
font.pixelSize: 18
anchors.centerIn: parent
color:"white"
}
Component.onCompleted: {
console.log("Component.onCompleted", mapToItem(canvas, 0, 0))
}
MouseArea {
anchors.fill: parent
onClicked: {
updateDotPosition(parent)
//here, printed coordinate is my expected
//but i want line them after tree node loaded antomate
console.log("updateDotPosition", mapToItem(canvas, 0, 0))
}
}
}
Row{
spacing: 40
anchors.horizontalCenter: parent.horizontalCenter
Loader {
id:leftLoader
onLoaded: {
console.log("leftLoader", mapToItem(canvas, 0, 0))
}
}
Loader {
id:rightLoader
onLoaded: {
console.log("rightLoader", mapToItem(canvas, 0, 0))
}
}
}
}
}
Canvas{
anchors.fill: parent
id:canvas
Loader {
id:pLoader
anchors.horizontalCenter: parent.horizontalCenter
//sourceComponent: rectangleComponent
}
}
Rectangle {
id: testMapToItemDot
width: 20
height: width
radius: width / 2
z: 1
color: "darkblue"
}
function updateDotPosition(itemToMap) {
var pos = testMapToItemDot.mapFromItem(
itemToMap,
(itemToMap.width - testMapToItemDot.width) / 2, // these parameters are optional - I want to move the dot to
(itemToMap.height - testMapToItemDot.height) / 2) // the center of the object, not upper left corner
testMapToItemDot.x += pos.x
testMapToItemDot.y += pos.y
}
}
加载项的位置和大小可以这样访问:Loader.item.x
、Loader.item.y
、Loader.item.width
、Loader.item.height
.
如果这不是您要查找的内容,请更准确地描述问题。
请查看此示例应用程序。我认为这就是您要找的东西 - 看看 function updateDotPosition(itemToMap)
。请注意,如果您将 "mapping" 指向一个不移动的对象(示例中的点在移动)并且该对象将是具有相同 x
的 Canvas
的同级对象, y
值,然后函数的结果将为您提供精确的点,从哪里画一条线。您将不需要像我一样使用 +=
。
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: appWindow
visible: true
width: 1066
height: 600
property int maxRectangles: 5
Component {
id: rectangleComponent
Rectangle {
x: 110
y: 30
width: 100
height: 100
property var loaderSource
Component.onCompleted: {
color = Qt.lighter("red", maxRectangles / 7)
if (maxRectangles-- > 0)
loaderSource = rectangleComponent
else
loaderSource = undefined
}
Loader {
sourceComponent: loaderSource
}
MouseArea {
anchors.fill: parent
onClicked: {
updateDotPosition(parent)
}
}
}
}
Loader {
sourceComponent: rectangleComponent
}
Rectangle {
id: testMapToItemDot
width: 20
height: width
radius: width / 2
z: 1
color: "darkblue"
}
function updateDotPosition(itemToMap) {
var pos = testMapToItemDot.mapFromItem(
itemToMap,
(itemToMap.width - testMapToItemDot.width) / 2, // these parameters are optional - I want to move the dot to
(itemToMap.height - testMapToItemDot.height) / 2) // the center of the object, not upper left corner
testMapToItemDot.x += pos.x
testMapToItemDot.y += pos.y
}
}
这是您示例的工作版本。这只是一个例子。不幸的是脏了。这是因为我有点难以理解代码中发生的事情——我相信你不会遇到这个问题。我还使用了 Timer
,因为创建时 Rectangle
对象的 x,y
等于 0
。我需要稍等一下。请不要在发布代码中使用它 - 这是糟糕的设计:)
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: appWindow
visible: true
width: 1066
height: 600
property var jsonData: [{"id":1,"pid":0},{"id":2,"pid":1},{"id":3,"pid":1},
{"id":4,"pid":2},{"id":5,"pid":2},{"id":6,"pid":3},
{"id":7,"pid":3},{"id":8,"pid":4},{"id":9,"pid":4},{"id":10,"pid":6}]
property int maxRectangles: 5
Component.onCompleted: {
var color = Qt.lighter("red", maxRectangles / 7)
pLoader.sourceComponent = rectangleComponent;
var currItem = pLoader.item;
currItem.color = "blue"
currItem.text = 0
connectedItems.push([currItem, null])
var tmp = {};
tmp[jsonData[0]["id"]] = currItem ;
for(var index = 1; index < jsonData.length; index++) {
color = Qt.lighter("red", index / 7)
var sItem = jsonData[index]["pid"];
if(tmp[sItem].rComponent.sourceComponent === null){
tmp[sItem].rComponent.sourceComponent = rectangleComponent
attachData(tmp[sItem].rComponent.item,index, color);
tmp[jsonData[index]["id"]] = tmp[sItem].rComponent.item ;
connectedItems.push([tmp[sItem].rComponent.item, null])
}
else {
tmp[sItem].lComponent.sourceComponent = rectangleComponent
attachData(tmp[sItem].lComponent.item,index, color);
tmp[jsonData[index]["id"]] = tmp[sItem].lComponent.item ;
connectedItems.push([tmp[sItem].lComponent.item, null])
}
if ( jsonData[index]["pid"] !== 0) {
connectedItems[connectedItems.length - 1][1] = connectedItems[jsonData[index]["pid"] - 1][0]
}
}
}
function attachData(item, text, color){
item.text = text;
item.color = color
}
property var connectedItems: [];
function paintConnection(objectFrom, objectTo) {
var vectorStart = canvas.mapFromItem(
objectFrom, objectFrom.width / 2, objectFrom.height)
var vectorEnd = canvas.mapFromItem(
objectTo, objectTo.width / 2,0)
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(vectorStart.x, vectorStart.y);
ctx.lineTo(vectorEnd.x,vectorEnd.y);
ctx.stroke();
canvas.requestPaint()
}
Timer {
id: paintLines
interval: 100
running: true
onTriggered: {
for (var i = 1 ; i < connectedItems.length ; i++) {
paintConnection(connectedItems[i][1].rect, connectedItems[i][0].rect)
}
}
}
Component {
id: rectangleComponent
Column{
property alias rComponent: rightLoader
property alias lComponent: leftLoader
property alias color: rect.color
property alias text: myText.text
property alias rect: rect
spacing: 40
//anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
id:rect
width: 100
height: 100
Text{
id:myText
font.pixelSize: 18
anchors.centerIn: parent
color:"white"
}
Component.onCompleted: {
console.log("Component.onCompleted", mapToItem(canvas, 0, 0))
}
MouseArea {
anchors.fill: parent
onClicked: {
updateDotPosition(parent)
//here, printed coordinate is my expected
//but i want line them after tree node loaded antomate
console.log("updateDotPosition", mapToItem(canvas, 0, 0))
}
}
}
Row{
spacing: 40
anchors.horizontalCenter: parent.horizontalCenter
Loader {
id:leftLoader
onLoaded: {
console.log("leftLoader", mapToItem(canvas, 0, 0))
}
}
Loader {
id:rightLoader
onLoaded: {
console.log("rightLoader", mapToItem(canvas, 0, 0))
}
}
}
}
}
Canvas{
anchors.fill: parent
id:canvas
Loader {
id:pLoader
anchors.horizontalCenter: parent.horizontalCenter
//sourceComponent: rectangleComponent
}
}
Rectangle {
id: testMapToItemDot
width: 20
height: width
radius: width / 2
z: 1
color: "darkblue"
}
function updateDotPosition(itemToMap) {
var pos = testMapToItemDot.mapFromItem(
itemToMap,
(itemToMap.width - testMapToItemDot.width) / 2, // these parameters are optional - I want to move the dot to
(itemToMap.height - testMapToItemDot.height) / 2) // the center of the object, not upper left corner
testMapToItemDot.x += pos.x
testMapToItemDot.y += pos.y
}
}