0

I'd like to mark a number of rows in my TreeTableView with red borders but I've run into the problem of table cells shifting away from their respective columns.

Visually it looks like this:

https://i.stack.imgur.com/GBiWz.png

style.css:

.style {
    -fx-border-style: solid line-join round ;
    -fx-border-color: ...;
}

For every column in the tree it seems to shift a little further from the right by what appears to be the width of the border (1px default). Not a problem with only 2 columns but the final application is supposed to hold a dozen of them.

I can set the insets of the border to be on the outside of the cells and that fixes the shifting but then you can't see the side borders anymore which also looks odd.

I'm guessing setting styles for a row is just convenience for having the engine set it for every cell.

Is there a way to stop the TreeTableCells from shifting? Maybe setting individual styles for the cells rather than styling the whole row?

1 Answers1

0

Assuming .style is applied to TreeTableRows:

.style {
    -fx-background-color: red, -fx-background ;
    -fx-background-insets: 0, 1 ;
}

I usually find I have to dig into the source for the default stylesheet to figure these out. You may want to mess with the insets and implement some kind of logic to prevent the double border on adjacent rows with the style class applied.

Here's an SSCCE:

import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableRow;
import javafx.scene.control.TreeTableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class StyledTreeTableView extends Application {

    private static final int MAX_VALUE = 1000 ;

    @Override
    public void start(Stage primaryStage) {
        TreeTableView<Item> treeTable = new TreeTableView<>();
        treeTable.setRoot(createTreeItem(1));

        treeTable.setRowFactory(ttv -> new TreeTableRow<Item>() {
            @Override
            public void updateItem(Item item, boolean empty) {
                super.updateItem(item, empty);
                if (empty) {
                    setText(null);
                    getStyleClass().remove("highlight");
                } else {
                    setText(item.toString());
                    if (item.getValue() % 10 == 3 || item.getValue() % 10 == 4) {
                        if (! getStyleClass().contains("highlight")) {
                            getStyleClass().add("highlight");
                        }
                    } else {
                        getStyleClass().remove("highlight");
                    }
                }
            }
        });

        TreeTableColumn<Item, String> nameCol = new TreeTableColumn<>("Item");
        nameCol.setCellValueFactory(cellData -> cellData.getValue().getValue().nameProperty());
        treeTable.getColumns().add(nameCol);

        for (int colIndex = 1 ; colIndex < 10 ; colIndex++) {
            TreeTableColumn<Item, Number> valueCol = new TreeTableColumn<>("Value * "+colIndex);
            final int multiplier = colIndex ;
            valueCol.setCellValueFactory(cellData -> cellData.getValue().getValue().valueProperty().multiply(multiplier));
            treeTable.getColumns().add(valueCol);
        }

        BorderPane root = new BorderPane(treeTable);
        Scene scene = new Scene(root, 600, 600);
        scene.getStylesheets().add("styled-tree-table.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TreeItem<Item> createTreeItem(int value) {
        Item item = new Item("Item "+ value, value);
        TreeItem<Item> treeItem = new TreeItem<>(item);
        if (value < MAX_VALUE) {
            for (int i = 0 ; i < 10; i++) {
                treeItem.getChildren().add(createTreeItem(value * 10 + i));
            }
        }
        return treeItem ;
    }

    public static class Item {
        private final StringProperty name = new SimpleStringProperty();
        private final IntegerProperty value = new SimpleIntegerProperty();

        public Item(String name, int value) {
            setName(name);
            setValue(value);
        }

        public final StringProperty nameProperty() {
            return this.name;
        }

        public final java.lang.String getName() {
            return this.nameProperty().get();
        }

        public final void setName(final java.lang.String name) {
            this.nameProperty().set(name);
        }

        public final IntegerProperty valueProperty() {
            return this.value;
        }

        public final int getValue() {
            return this.valueProperty().get();
        }

        public final void setValue(final int value) {
            this.valueProperty().set(value);
        }


    }

    public static void main(String[] args) {
        launch(args);
    }
}

with the stylesheet:

.highlight {
    -fx-background-color: red, -fx-background ;
    -fx-background-insets: 0, 1 ;
}
James_D
  • 201,275
  • 16
  • 291
  • 322
  • Ah, `TreeTableView`, not `TableView`. Updated accordingly and added example. – James_D Sep 25 '15 at 17:22
  • That is pretty much what I was looking for, the double borders aren't much of an issue really. If I understand the CSS right, then this sets the background of the row to be red then overlays it with the default? Anyhow, thanks for the tip, complete with code! – Plsplsplsplsplspls Sep 28 '15 at 10:27