Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set row foreground color of a tableView on JavaFX?

I have a tableView in which i have a lot of items, and in some of these items i need to set the foreground color to red. So it is dynamically set. What i did successfully was to add a rowFactory to the table and change the background color through css, but foreground doesn't change. It's always black:

tableViewAbastecidas.setRowFactory(param -> new TableRow<LeituraPista>() {
    @Override
    protected void updateItem(LeituraPista item, boolean empty) {
        if (item == null) {
            return;
        }
        String estilo;
        if (tableViewAbastecidas.getSelectionModel().getSelectedItems().contains(item)) {
            estilo = "-fx-background-color: linear-gradient(#95caff 0%, #77acff 90%, #e0e0e0 90%);";
        } else {
            estilo = "-fx-background-color: linear-gradient(white 0%, white 90%, #e0e0e0 90%);";
        }
        if (myConditionIsTrue) {
            estilo += "-fx-fill: #ff0000;-fx-text-fill: chartreuse;"; //Doesn't work, always black
        }
        setStyle(estilo);
    }
});
like image 282
Mateus Viccari Avatar asked Jan 27 '15 13:01

Mateus Viccari


1 Answers

In my experience, it always works better to put the style in an external style sheet.

I think the issue you have is that TableRow doesn't support a -fx-text-fill property; it is supported by the TableCells it contains. You could set cell factories on all the columns, but if you use an external style sheet you can manipulate the style class of the row and then alter the text fill of it, and its descendants (since css styles will be inherited by child nodes).

Since you're using JavaFX 8, you can use PseudoClasss, which have a much cleaner API than manipulating the list of style classes.

So (I haven't tested this directly)

// the string "my-condition" is the name of the pseudoclass and appears in the 
// external css file (see below):
PseudoClass myConditionPseudoClass = PseduoClass.getPseudoClass("my-condition");

tableViewAbastecidas.setRowFactory(param -> new TableRow<LeituraPista>() {
    @Override
    protected void updateItem(LeituraPista item, boolean empty) {
        super.updateItem();
        pseudoClassStateChanged(myConditionPseudoClass,  (! empty) && myCondition);
    }
});

And then you do all the style in an external CSS file:

.table-row-cell {
    -fx-background-color: linear-gradient(white 0%, white 90%, #e0e0e0 90%);
}
.table-row-cell:selected {
    -fx-background-color: linear-gradient(#95caff 0%, #77acff 90%, #e0e0e0 90%);
}
.table-row-cell:my-condition .table-cell {
    -fx-fill: #ff0000;
    -fx-text-fill: chartreuse;    
}

Here is a complete example:

import java.util.Random;
import java.util.stream.IntStream;

import javafx.application.Application;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TableRowStyleExample extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Item> table = new TableView<>();

        TableColumn<Item, String> nameCol = new TableColumn<>("Name");
        nameCol.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getName()));

        TableColumn<Item, Number> valueCol = new TableColumn<>("Value");
        valueCol.setCellValueFactory(cellData -> new ReadOnlyIntegerWrapper(cellData.getValue().getValue()));

        table.getColumns().add(nameCol);
        table.getColumns().add(valueCol);

        final Random rng = new Random();
        IntStream.rangeClosed(1, 20)
            .mapToObj( i -> new Item("Item "+i, rng.nextInt(10)+1))
            .forEach(table.getItems()::add);

        PseudoClass highValuePseudoClass = PseudoClass.getPseudoClass("high-value");
        table.setRowFactory(tv -> new TableRow<Item>() {
            @Override
            public void updateItem(Item item, boolean empty) {
                super.updateItem(item, empty);
                pseudoClassStateChanged(highValuePseudoClass, (! empty) && item.getValue() >= 9);
            }
        });

        Scene scene = new Scene(new BorderPane(table), 600, 400);
        scene.getStylesheets().add("table-row-style-example.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static class Item {
        private final String name ;
        private final int value ;

        public Item(String name, int value) {
            this.name = name ;
            this.value = value ;
        }

        public String getName() {
            return name ;
        }

        public int getValue() {
            return value ;
        }
    }

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

table-row-style-example.css

.table-row-cell {
    -fx-background-color: linear-gradient(white 0%, white 90%, #e0e0e0 90%);
}
.table-row-cell:selected {
    -fx-background-color: linear-gradient(#95caff 0%, #77acff 90%, #e0e0e0 90%);
}
.table-row-cell:high-value .table-cell {
    -fx-text-fill: chartreuse;    
} 
like image 67
James_D Avatar answered Nov 14 '22 23:11

James_D