문제

오브젝트의 트리를 생성하면 트리는 매우 간단한 논리를 사용하여 그려집니다.

  • 각 대상은 자체 대표와 자녀 (그리고 자녀 등 ...)
  • 객체가 부모의 첫 번째 자식이면 시각적 인 표현
  • 에서 들여 쓰기가 그려집니다.
  • 모든 다음 물체는 이전 형제
  • 에 직접 그려집니다.

그러나이 간단한 알고리즘은 어떤 경우에 새 객체를 삽입 할 때 실패합니다. 예 :

여기에 이미지 설명을 입력하십시오

노드 1과 2가 노드 0 (모든 노드의 왼쪽 검은 선)이 자체 UI와 자녀 모두의 합계가되는 노드 0 (모든 노드의 검은 선)이 전체 높이가 성공적으로 삽입됩니다.

노드 1이 노드 1에 삽입 될 때, 레이아웃 중단 - 노드 2는 새로 삽입 된 노드와 겹치지 않고 검은 선을 보이지 않게 만듭니다.

추가 리프레시주기가 트리거되면 트리가 정상으로 돌아갑니다. 그래서 글리치는 일부 임시 "또는 동기화"속성에 의해 원인이어야합니다. 삽입물이 발생한 위치에 따라 하나의 여분의 새로 고침이 항상 순서대로 주문하는 것은 아닙니다. 때로는 정렬을 방해하는 것으로부터 "캐스케이드 아웃"으로 몇 가지 새로 고침 사이클을 가져갈 수 있습니다.

아이디어 가이 잘못된 행동을 일으키는 일과 / 또는이를 고치는 방법을 일으킬 수 있습니다. 코드가 가끔씩 중단되는 이유로, 궁극적으로 작동하지만 그 이유는 궁극적으로 작동하더라도 여러 번의 새로 고침이 필요합니까?

편집 : Level에서 마지막 노드를 종료하지 않는 노드에 삽입 할 때 정렬 틈이있는 경우를 분리하고 정확하게 분리 할 수있었습니다. 모든 바인딩은 각각의 새 노드가 마지막 노드에 삽입되고 "열려"예를 들어, 예를 들어 올바르게 전파됩니다. 그 레벨에 다음 노드가 없지만 이전 노드에 삽입하는 것은 바인딩을 해제합니다. 따라서 추가적인 새 레벨이 영향을 미치는 모든 수준을 통해 버그를 단계적으로 위로하는 데 추가적인 새로 고침주기가 필요합니다. 그러나 나는 아직도 그것이 일어나는 일 때만 그것을 고치는 방법과 그것을 고치는 것이 아직도 모른다.

편집 : 조금 더 조사하면 새 자식이 부모 아이템에 삽입되고 자식이 주문을 기준으로 자식을 다시 정렬하면 부모의 childrenRect 속성이 바로 변화를 반영하지 않습니다. ...에 따라서 삽입 된 물체의 다음 형제가 위치되면 객체 높이에 대해 오래된 오래된 값을 사용하므로 새로 삽입 된 객체가 사용하지 않으므로 영향을주지 않습니다. 그래서 다음 큰 질문은 알고리즘이 올바른 데이터로 예상대로 작동 할 수 있도록 바인딩을 수행해야하므로 바인딩이 수행 될 수 있도록하는 방법은 무엇입니까? 나는 작업을 지연시키기 위해 타이머를 사용하여 시도했지만, 그것이 시간 문제이지만 논리적 인 순서에 대해서는, 예를 들어, 현재 발생한 부서와 동일한 버그를 제거하는 데 필요한 새로 고침 수입니다.

편집 : 나는 "그것을 해결"하는 방법을 알았지 만 ... 정말로, 나는 아직도 그것을 피하는 방법과 그것을 피하는 방법을 모른다. 그러나 전체 트리를 업데이트하는 것보다 조금 더 "경제적 인"해결책이 될 것입니다. 고정되어 부모님을 내려 가서 루트에 도달 할 때까지 현재 분기 만 업데이트하십시오. 이것은 많은 것을 저장하지만 바인딩이 작동하기로되어있는 것처럼 바로 올바른 값을 꺼내는 것이 좋습니다.

편집 : 여기에 주문 코드가 있습니다.

for (int i = 0; i < _children.size(); ++i) {
        UI * ui = _children.at(i)->_ui;
        if (ui) {
            if (i) {
                UI * prev = _children.at(i-1)->_ui;
                ui->setX(prev->x());
                ui->setY(prev->height() + prev->y());
            } else {
                ui->setX(Object::_helper->nodeSize());
                ui->setY(_ui->childOffset());
            }
        }
    }
.

및 QML이 설정되는 방법 :

UI {
    id: main
    width: childrenRect.width
    height: childrenRect.height    

    Item { 
        height: childrenRect.height

        Rectangle {
            width: Helper.nodeSize
            height: Helper.nodeSize
            color: "red"

            Text {
                anchors.centerIn: parent
                text: main.id
            }

            MouseArea {
                anchors.fill: parent   
                acceptedButtons: Qt.LeftButton | Qt.RightButton                 
                onClicked: {
                    if (mouse.button == Qt.RightButton)
                        Helper.gotoXY(main.absolutePosition())
                    else {
                        Helper.createObject(1, main)
                        Helper.updateRoot()
                    }
                }

                Rectangle {
                    height: main.height
                    width: 10
                    x: -10
                    color: "black"
                }
            }
        }
    }
}
.

도움이 되었습니까?

해결책

그것에 대해 생각할 때, 그 행동은 완벽한 의미가 있으므로 바인딩에는 아무런 문제가 없습니다.

"계단식 업데이트"가 작동하는 이유는 매우 간단하고 코드가 작동하지 않는 이유와 해결 방법을 지적합니다.

기본적으로 새 노드를 삽입하면 "마지막"노드를 삽입하는 한 코드가 부러지지 않는 "노드"로 모든 것을 푸시합니다. 그러나 끝이 아닌 경우 모든 것을 조금 밀어 넣지 만이 변경은 상위 위치가 위치를 업데이트 할 때까지 반영되지 않습니다. 루트에서 업데이트를 호출하고 삽입물이 더 깊어지지 않은 경우 첫 번째 패스는 높이의 바인딩의 첫 번째 업데이트 만 트리거링되므로 다음 갱신주기 다음 형제 자매가 올바르게 배치 될 수 있습니다. 삽입물이 더 깊어지면 일어날 필요가있는 바인딩이 더 많을 것입니다.

새 노드가 올바르게 삽입 된 이유는 자체 삽입이 아직도 업데이트되지 않은 값을 사용하는 다음 업데이트가 표시 될 때까지 자체 삽입이 변경되지 않고 바인딩을 평가하여 시작하여 킥을 찰립니다. 다음주기.

나는 이것을하는 가장 빠른 방법이 삽입물의 수준에서 시작하고 업데이트 "바깥 쪽"과 "아래쪽"예를 들어, "바깥 쪽"을 전파하는 것입니다. 모든 다음 개체를 업데이트 한 다음 부모의 다음 형제 자매가 루트 오브젝트를 누르기까지 다음 부모의 형제 자매입니다. 이것은 "아래"및 삽입물의 영향을받는 객체 만 재배치되며 현재 최상의 솔루션에 비해 많은주기를 면도해야합니다.

다른 팁

QML과 JS를 조금씩 놀았으며 그래픽 UI 문제가 없음을 조정했습니다.

my 데모 프로젝트 자녀 객체를 추가 할 수 있습니다.나무 (빨간색 상자에 왼쪽 및 오른쪽 클릭).논리가 완료되지 않지만 기본 사항은 매우 원활하게 실행됩니다.

main.qml

import QtQuick 2.1
import QtQuick.Controls 1.0

ApplicationWindow {
    id: app
    width: 800
    height: 600

    property int lastNodeId: 0
    function getId() { return lastNodeId++; }

    Level { }
}
.

Level.qml

import QtQuick 2.0

Item {
    id: frame
    width: childrenRect.width
    height: childrenRect.height

    Rectangle {
        width: 10
        color: "#000000"
        height: parent.height
        x: 0
        y: 0
    }

    Column {
        x: 10
        id: content

        Position { }
    }
}
.

빨간색 상자와 주변 아이템은 형제 자매를 배치 할 수 있습니다

import QtQuick 2.0
import "component_creation.js" as CC

Item {
    id: position0
    width: childrenRect.width
    height: childrenRect.height

    Rectangle {
        color: "red"
        width: 80
        height: 30

        Text {
            anchors.fill: parent
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter

            Component.onCompleted: text = app.getId() // Set once, avoid bindung

            MouseArea {
                anchors.fill: parent
                acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
                onClicked: {
                    if (mouse.button == Qt.LeftButton)
                    {
                        CC.createChild(position0);
                    }
                    else if (mouse.button == Qt.RightButton)
                    {
                        CC.createSiblingAfter(position0)
                    }
                    else if (mouse.button == Qt.MiddleButton)
                    {
                        // no clue how to implement
                        // CC.createSiblingBefore(position0)
                    }
                }
            }
        }
    }
}
.

및 일부 JavaScript : Position.qml

function createChild(parent_item) {
    var component = Qt.createComponent("Level.qml");
    if (component.status == Component.Ready)
    {
        var sprite = component.createObject(parent_item, {"x": 70, "y": 30});
        if (sprite == null) console.log("Error creating Level object");
    }
    else
    {
        console.log("Error loading component:", component.errorString());
    }
}

function createSiblingAfter(sibling_position)
{
    var component = Qt.createComponent("Position.qml");
    if (component.status == Component.Ready)
    {
        var sprite = component.createObject(sibling_position.parent);
        if (sprite == null) console.log("Error creating Position object");
    }
    else
    {
        console.log("Error loading component:", component.errorString());
    }
}
.

도움이되기를 바랍니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top