Modify the indices of each item in a Treeview Java FX or Treeview.getSelectionModel() override method. select(int index)?

Asked

Viewed 220 times

2

Greetings to all. This is my first post here.

I am developing a Java FX project that consists of a form with a Treeview whose items are obtained from an Arraylist, previously completed through a database query.

inserir a descrição da imagem aqui

This table represents an item hierarchy where each item has an id, name and parent_id (id of another table item, taken as the parent of the item in question).

To mount tree I am using a foreach to select the item in the tree whose id corresponds to the parent_id (c.getParent) of each item to be added :

for (Conta c : list){
    try {
        tree.getSelectionModel().select(c.getParent());

        MyTreeItem item = (MyTreeItem)tree.getSelectionModel().getSelectedItem();
        item.setExpanded(true);

        MyTreeItem conta = new MyTreeItem (c.getNome(),c.getId());
        item.getChildren().add(conta);
    } catch (Exception e) {
        System.out.println(e);
    }
}

This method worked as I expected:

inserir a descrição da imagem aqui

When I first ran the project the table already had the records and the tree was mounted correctly. Then I implemented methods to add children to any node selected by the user. The problem is that I realized that although the method is saving the new item correctly in the BD (see image below), if I update the tree, or close and open the program again, the tree will display the newly added item as the child of an item other than the one chosen and that is pointed out by the parente_id field as parent.

Itens recém criados no BD

Note that the item "Current account 6666" (parent_id = 15) should be the child of the "Bank of Boston" account (id = 15)

Items recém criados no sistema

Then I created a custom Treeitem with the id and name parameters for, when mounting the tree try to organize the hierarchy using as a criterion the id that the element represented in the tree has in the database. It was then that I realized that the problem lies in this line: tree.getSelectionModel().select(c.getParent()); because it selects the item by index in Treeview, only this index does not match the id of the element in the database.

My question is how do I make that line of code tree.getSelectionModel().select(int index); select an item in a Treeview not by the index parameter (item position in Treeview(?)), but using as parameter the identifier (int id) that I created in a class derived from Treeitem with this attribute.

Thanks to everyone from now on.

1 answer

1


I did a little different from your proposal and for me it worked correctly, I will explain step by step as I did:

List<TreeItem<Conta>> treeItems = new ArrayList<>();

// Criando todos os tree itens
for (Conta c: contas) {
    TreeItem<Conta> newItem = new TreeItem<Conta>(c);
    treeItems.add(newItem);
}

// Adicionando filhos dos nós
for (TreeItem<Conta> no : treeItems) {
    // Pega o id do nó
    int id = no.getValue().getId();

    // Busca os nós que tem como parentId o id do pai
    List<TreeItem<Conta>> filhos = treeItems.stream()
                .filter( filho -> filho.getValue().getParent_id() == id)
                .collect(Collectors.toList());

    // Adiciona-os como filhos
    no.getChildren().setAll(filhos);
}

// Adiciona o nó root na árvore 
TreeView<Conta> tree = new TreeView<>(treeItems.get(0));

First I created all the Treeitems from the account array, and only then I was navigating through the created nodes and adding the children. So far I don’t know if it’s too different but I don’t know if you’ve noticed that Train accepts a type through Generics.

Note: In order for the object name in Treeview not to be weird you have to override the toString method of the class account in this way:

@Override
public String toString() {
    return nome; // Vai retornar apenas o nome do objeto como representação
}

To add new ones I did the following:

Button adicionarNo = new Button("Adicionar nó");
adicionarNo.setOnAction((ActionEvent) -> {
    // Pega uma referência ao item selecionado ao invés de usar o Index
    TreeItem<Conta> itemSelecionado = tree.getSelectionModel().getSelectedItem();

    // Verifica se a seleção não está vazia, para evitar NPE
    if(itemSelecionado != null) {
        int idpai = itemSelecionado.getValue().getId();

        // Adiciona a conta no banco de dados,
        // Aqui você pode retornar o id da nova conta criada no banco
        int idconta = 0; //adicionaConta("Nome do item", idpai);

        TreeItem<Conta> novoItem = new TreeItem<Conta>(new Conta(idconta, idpai, "Nome do item"));
        itemSelecionado.getChildren().add(novoItem);
   }
});

That way I could create new knots anywhere in the tree without problems.

  • 1

    I did a new project and added your code to replace the one I was using. I ran the application and it apparently worked except because the tree items are displaying the memory addresses of the objects(guess this is it)Try_FX.png. How do I display only the account name on the tree? I tried something like "no.getChildren(). setAll(sons);" or "treeItems.add(newItem.getValue();" but I couldn’t... Any hint?

  • I forgot to mention this detail. Whenever we use objects we have to say how it will be represented by overwriting the toString method. I will change the answer.

  • Very good! I followed your guidance and overwritten toString, then implemented the necessary SQL methods to insert the new items from the tree into the BD and added to the logic you used for the add button. Following the same reasoning I also made a button/method to remove the items from the tree and the bank. It worked perfectly.Thank you very much.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.