0

I am creating a qml qt project that creates a binary based on user input for educational purposes. You could say I am new to qt but I do know some basic concepts. I am using a recursive function to create a binary node with the value entered by the user. The recursive function checks the value entered with the root node of the binary tree and then continues on recursively until it finds the location in the tree without the node. I have only worked out the left side of this tree, so it will only work with values that are less than the nodes. Here is the algorithm for inserting the node:

void BinaryTree::insert_node(QQuickItem* parent_node, QString node_text) {
    double node_value = node_text.toDouble();
    root_node_value = parent_node->property("node_text").toInt();

    if (node_value < root_node_value) {
        if (!parent_node->property("has_left_node").toBool()) {
            QQuickItem *left_node = create_binary_node(parent_node, node_text, "left_node");
            QObject *node_anchors = qvariant_cast<QObject*>(left_node->property("anchors"));
            node_anchors->setProperty("right", parent_node->property("right"));
            node_anchors->setProperty("rightMargin", 60);
            left_node->setProperty("id", "left_node");
            left_node->setProperty("objectName", "left_node");
            parent_node->setProperty("has_left_node", true);
        } else {
            QQuickItem* left_node = parent_node->findChild<QQuickItem*>("left_node");
            if (left_node) {
                insert_node(left_node, node_text);
            } else {
                std::cout << "left_node doesn't exist" << std::endl;
            }
        }
    }
};

The function works perfectly for the root node and the second node but for the 3rd node, it can't find the second node that was created, it just prints "left_node doesn't exist". Here is the function I use to start the creation of the tree and to create a node:

void BinaryTree::create_node(QString node_text) {
    if (node_count == 0) {
        double node_value = node_text.toDouble();
        QString node_id = "node_" + QString::number(node_count);

        QQuickItem *node = qobject_cast<QQuickItem*>(node_component->create());
        node->setParentItem(qobject_cast<QQuickItem*>(node_parent));
        node->setProperty("node_text", node_text);
        node->setProperty("id", node_id);

        QObject *node_anchors = qvariant_cast<QObject*>(node->property("anchors"));
        node_anchors->setProperty("horizontalCenter", node_parent->property("horizontalCenter"));
        node_anchors->setProperty("top", node_parent->property("top"));
        node_anchors->setProperty("topMargin", 10);
        root_node = node;
        root_node_value = node_value;
    } else {
        insert_node(root_node, node_text);
    }
    
    node_count++;
};

QQuickItem* BinaryTree::create_binary_node(QQuickItem* parent_node, QString node_text, QString node_id) {
    QQuickItem* node = qobject_cast<QQuickItem*>(node_component->create());
    node->setParentItem(parent_node);
    node->setProperty("node_text", node_text);
    node->setProperty("id", node_id);
    node->setProperty("objectName", node_id);

    QObject *node_anchors = qvariant_cast<QObject*>(node->property("anchors"));
    node_anchors->setProperty("top", parent_node->property("top"));
    node_anchors->setProperty("topMargin", 60);

    return node;
}

The Node component that is being created is a qml file that contains this:


Rectangle {
    width: 50
    height: 50
    radius: Math.min(width, height)/2
    color: "cyan"

    property string node_text
    property bool has_right_node: false
    property bool has_left_node: false

    Text {
        font.pixelSize: 12
        anchors.centerIn: parent
        text: node_text
    }
}

I don't even know where to begin with this problem but I have been able to pinpoint the problem to either:

  1. The node that is being created goes out of scope so it can't be found in the next iteration of the function.
  2. When creating the node there is an error in assigning the object name for the node, to fix this I repeated the lines for adding the object name and id outside of the function as well.

Other things that I have tried are:

  1. printing the property of the newly created node to make sure it has an object name
  2. adding if-else statements to check if the find child returns a value

I would love a solution for this problem, if I need to change anything with my question pleae tell me.

Thank you in advance.

2
  • id isn't a regular propertry, I don't think you can set it in this way, use objectName instead Commented Nov 9, 2023 at 12:25
  • @folibis I am using objectName to set the object name for the newly created node, and I tried removing the id property from the node component but that doesn't change anything Commented Nov 9, 2023 at 15:48

1 Answer 1

0

If you come up with a creative hierarchy model, and, if you realize with a recursive Loader, you can move your tree-logic to QML:

import QtQuick
import QtQuick.Controls
Page {
    background: Rectangle { color: "#888" }
    DrawNode {
        anchors.fill: parent
        model: ({
            txt: "root",
            children: [
                {
                    txt: "child1",
                    children: [
                        {
                            txt: "gchild1",
                            children: [
                                {
                                    txt: "ggchild1"
                                },
                                {
                                    txt: "ggchild2"
                                }
                            ]
                        },
                        {
                            txt: "gchild2"
                        }
                    ]
                },
                {
                    txt: "child2",
                    children: [
                        {
                            txt: "gchild3"
                        }
                    ]
                }
            ]
        })
    }
}

// DrawNode.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Shapes
Item {
    id: frame
    property var model
    Rectangle {
        x: frame.width / 2 - width / 2
        y: 10
        width: 80
        height: 80
        radius: 40
        border.color: "black"
        Text {
            anchors.centerIn: parent
            text: model.txt
        }
    }
    Repeater {
        model: frame.model.children
        Item {
            anchors.fill: parent
            z: -1
            Shape {
                ShapePath {
                    startX: frame.width / 2
                    startY: 50
                    strokeColor: "black"
                    PathLine {
                        x: index * frame.width / 2 + frame.width / 4
                        y: 150
                    }
                }
            }
            Loader {
                x: index * frame.width / 2
                y: 100
                width: frame.width / 2
                height: frame.height - 100
                Component.onCompleted: setSource("DrawNode.qml",{model:modelData})
            }
        }
    }
}

You can Try it Online!

DrawNode.gif

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.