pawchi
pawchi

Reputation: 143

javafx treeTableView mark children rows red

I have problem with marking color of treeTableView row. Marking "first level" row is no problem and the code functions. Under updateItem method -> item, I can access first row fruit properties.

enter image description here

But I dont know how to access deeper in "second level" of treeTableView and color the rows?

enter image description here

Below is my code. Thanks in advance for any help.

import javafx.fxml.Initializable;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableRow;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ResourceBundle;

public class ControllerWindowTest implements Initializable {

    public TreeTableView<Fruit> treeTableView;
    ArrayList<Fruit> fruitsList = new ArrayList<>(Arrays.asList(
            new Fruit("Apple", "round", "green"), new Fruit("Apple", "round", "red"),
            new Fruit("Apple", "round", "yellow"), new Fruit("Plum", "round", "yellow"),
            new Fruit("Plum", "round", "navy blue"), new Fruit("Plum", "oval", "red")));

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        createTreeTable();
        fillTreeTable();
    }

    public void buttonMarkFruits(){
        treeTableView.setRowFactory(ttv -> new TreeTableRow<Fruit>(){
            @Override
            protected void updateItem(Fruit item, boolean empty) {
                super.updateItem(item, empty);
                //Fruit item - is here "first level" of treeTableView(TreeItem: apples, plums).
                // How to go deeper to second level to access children of apples, plums -
                // where I can check color of fruit and mark treeTable row red??
                if (item == null) {
                    setStyle(null);
                } else if (item.getColor().equals("red")){
                    setStyle("-fx-background-color: tomato;");
                } else {
                    setStyle(null);
                }
            }
        });
    }

    public void createTreeTable(){
        TreeTableColumn<Fruit, String> colName = new TreeTableColumn<>("Fruit");
        TreeTableColumn<Fruit, String> colShape = new TreeTableColumn<>("Shape");
        TreeTableColumn<Fruit, String> colColor = new TreeTableColumn<>("Color");

        colName.setCellValueFactory(new TreeItemPropertyValueFactory<>("name"));
        colShape.setCellValueFactory(new TreeItemPropertyValueFactory<>("shape"));
        colColor.setCellValueFactory(new TreeItemPropertyValueFactory<>("color"));

        treeTableView.getColumns().addAll(colName, colShape, colColor);
    }

    public void fillTreeTable(){
        TreeItem root = new TreeItem(new Fruit("", "", ""));
        TreeItem apples = new TreeItem(new Fruit("Apple", "", ""));
        TreeItem plums = new TreeItem(new Fruit("Plum", "", ""));
        for (Fruit fruit: fruitsList){
            if (fruit.getName().equals("Apple")){
                apples.getChildren().add(new TreeItem<>(new Fruit("", fruit.getShape(), fruit.getColor())));
            }
            if (fruit.getName().equals("Plum")){
                plums.getChildren().add(new TreeItem<>(new Fruit("", fruit.getShape(), fruit.getColor())));
            }
        }
        root.getChildren().addAll(apples,plums);
        root.setExpanded(true);
        treeTableView.setRoot(root);
        treeTableView.setShowRoot(false);
    }
}

Upvotes: 0

Views: 450

Answers (1)

James_D
James_D

Reputation: 209319

The problem is not that the rows are not in the "first level" of the tree; it's that the table row's updateItem() method is not called when the button is pressed.

The basic idea is to have some kind of observable property that the rows observe, so that they update the styles as needed. Use that row implementation whether or not the button is pressed (so set the row factory in the initialize() method), and just update the property when the button is pressed. A minimal implementation of this will look like:

public class ControllerWindowTest implements Initializable {

    @FXML
    private TreeTableView<Fruit> treeTableView;
    
    private BooleanProperty redFruitsMarked = new SimpleBooleanProperty(false);
    
    ArrayList<Fruit> fruitsList = new ArrayList<>(Arrays.asList(
            new Fruit("Apple", "round", "green"), new Fruit("Apple", "round", "red"),
            new Fruit("Apple", "round", "yellow"), new Fruit("Plum", "round", "yellow"),
            new Fruit("Plum", "round", "navy blue"), new Fruit("Plum", "oval", "red")));

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        createTreeTable();
        fillTreeTable();
        treeTableView.setRowFactory(ttv -> new TreeTableRow<Fruit>(){
            
            {
                redFruitsMarked.addListener((obs, wereMarked, areNowMarked) -> updateStyles());
            }
            
            @Override
            protected void updateItem(Fruit item, boolean empty) {
                super.updateItem(item, empty);
                updateStyles();
            }
            
            private void updateStyles() {
                                
                if (getItem() == null || (! redFruitsMarked.get())) {
                    setStyle(null);
                } else if (getItem().getColor().equals("red")){
                    setStyle("-fx-background-color: tomato;");
                } else {
                    setStyle(null);
                }
            }
        });
    }

    @FXML
    private void buttonMarkWires(){
        redFruitsMarked.set(true);
    }

    public void createTreeTable(){
        TreeTableColumn<Fruit, String> colName = new TreeTableColumn<>("Fruit");
        TreeTableColumn<Fruit, String> colShape = new TreeTableColumn<>("Shape");
        TreeTableColumn<Fruit, String> colColor = new TreeTableColumn<>("Color");

        colName.setCellValueFactory(new TreeItemPropertyValueFactory<>("name"));
        colShape.setCellValueFactory(new TreeItemPropertyValueFactory<>("shape"));
        colColor.setCellValueFactory(new TreeItemPropertyValueFactory<>("color"));

        treeTableView.getColumns().addAll(colName, colShape, colColor);
    }

    public void fillTreeTable(){
        TreeItem<Fruit> root = new TreeItem<>(new Fruit("", "", ""));
        TreeItem<Fruit> apples = new TreeItem<>(new Fruit("Apple", "", ""));
        TreeItem<Fruit> plums = new TreeItem<>(new Fruit("Plum", "", ""));
        for (Fruit fruit: fruitsList){
            if (fruit.getName().equals("Apple")){
                apples.getChildren().add(new TreeItem<>(new Fruit("", fruit.getShape(), fruit.getColor())));
            }
            if (fruit.getName().equals("Plum")){
                plums.getChildren().add(new TreeItem<>(new Fruit("", fruit.getShape(), fruit.getColor())));
            }
        }
        root.getChildren().addAll(apples,plums);
        root.setExpanded(true);
        treeTableView.setRoot(root);
        treeTableView.setShowRoot(false);
    }
}

Upvotes: 3

Related Questions