Marcos
Marcos

Reputation: 5017

Tableview row style

I have a tableview which I want to apply depend on a value of row item diferent styles.

For example:

Each row represents a person with a property years, so If person < 18 years, row color should be red. If person > 60 years, row color should be greeen...

I search over SO about apply style to rows, but most cases try to apply to selected rows and others use cellfactories (I don't know if is possible to style a whole row or I need to apply style to each field).

Upvotes: 1

Views: 546

Answers (1)

James_D
James_D

Reputation: 209330

Just set a row factory. The best way to manage the styles is to use CSS PseudoClasss. In your example you could have one for "young" and one for "old":

PsuedoClass old = PseudoClass.getPseudoClass("old");
PsuedoClass young = PseudoClass.getPseudoClass("young");
tableView.setRowFactory(tv -> {
    TableRow<Person> row = new TableRow<>();
    ChangeListener<Number> yearsListener = (obs, oldAge, newAge) -> {
        int age = newAge.intValue();
        row.pseudoClassStateChanged(old, age > 60);
        row.pseudoClassStateChanged(young, age < 18);
    };
    row.itemProperty().addListener((obs, previousPerson, currentPerson) -> {
        if (previousPerson != null) {
            previousPerson.yearsProperty().removeListener(yearsListener);
        }
        if (currentPerson != null) {
            currentPerson.yearsProperty().addListener(yearsListener);
            row.pseudoClassStateChanged(old, currentPerson.getYears() > 60);
            row.pseudoClassStateChanged(young, currentPerson.getYears() < 18);
        } else {
            row.pseudoClassStateChanged(old, false);
            row.pseudoClassStateChanged(young, false);
        }
    });
    return row ;
});

If you know the years are fixed for each Person (i.e. they won't change while the table is displayed), you can simplify this to

PsuedoClass old = PseudoClass.getPseudoClass("old");
PsuedoClass young = PseudoClass.getPseudoClass("young");
tableView.setRowFactory(tv -> {
    TableRow<Person> row = new TableRow<>();
    row.itemProperty().addListener((obs, previousPerson, currentPerson) -> {
        if (currentPerson != null) {
            row.pseudoClassStateChanged(old, currentPerson.getYears() > 60);
            row.pseudoClassStateChanged(young, currentPerson.getYears() < 18);
        } else {
            row.pseudoClassStateChanged(old, false);
            row.pseudoClassStateChanged(young, false);
        }
    });
    return row ;
});

Now to apply style just create an external style sheet with the styles you want:

.table-row-cell:young {
    -fx-background: green ;
}
.table-row-cell:old {
    -fx-background: blue ;
}

Upvotes: 3

Related Questions