问题
I have a list view of Labels and I want to color the list cells on run time. The problem is that I want to fill the entire Cell with the color not only the background of the Label. Is there way to do it in Java/CSS?
回答1:
Understanding the dynamic nature of ListView cell coloring
Normally, the inner cell color changes based upon a number of things:
- Whether the cell is an odd or even row (even rows have a lighter background).
- Whether the row is selected.
- Selected rows have different colors depending upon whether the control has focus or not (a focused selected row is blue, an unfocused selected row is gray).
So because the cell color can change based upon the state, you need to decide if you want to retain this behavior or not when you set custom coloring for your cells.
Sample Solution
Here is an example which will set the cell color to a pale green color depending upon whether a list item matches a criteria (in this case hardcoded for testing purposes to a name beginning with the letter 'J').
import javafx.application.Application;
import javafx.collections.*;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ColoredList extends Application {
private static final ObservableList<String> data = FXCollections.observableArrayList(
"Jill",
"Jack",
"Tom",
"Harry",
"Jenney"
);
private static final String DEFAULT_CONTROL_INNER_BACKGROUND = "derive(-fx-base,80%)";
private static final String HIGHLIGHTED_CONTROL_INNER_BACKGROUND = "derive(palegreen, 50%)";
@Override
public void start(Stage stage) throws Exception {
ListView<String> listView = new ListView<>(data);
listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> param) {
return new ListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setStyle("-fx-control-inner-background: " + DEFAULT_CONTROL_INNER_BACKGROUND + ";");
} else {
setText(item);
if (item.startsWith("J")) {
setStyle("-fx-control-inner-background: " + HIGHLIGHTED_CONTROL_INNER_BACKGROUND + ";");
} else {
setStyle("-fx-control-inner-background: " + DEFAULT_CONTROL_INNER_BACKGROUND + ";");
}
}
}
};
}
});
VBox layout = new VBox(listView);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(ColoredList.class);
}
}
Some things to note:
- The custom cell rendering is accomplished via a custom cell factory for the ListView.
- The cells returned by the cell factory, set the
-fx-control-inner-background
looked-up CSS color depending upon the cell state. If you don't know what a looked-up color is, look it up in the the JavaFX CSS reference guide and look at themodena.css
file in the jfxrt.jar file that ships with your Java install. - The default cell rendering mechanism will slightly darken or lighten even and odd rows in the ListView, even based upon your custom color.
- The sample only sets custom colors for non-selected rows. For selected rows, the default blue and gray colors are retained. So the sample is not comprehensive, but hopefully provides enough information for you to accomplish what you want.
- The sample codes the default and custom colors in code, but a larger app would be better off having these defined in a separate user CSS stylesheet.
回答2:
In your cell factory's updateItem
function, just use the following lines:
if(getIndex() % 2 == 1)
setStyle("-fx-background-color: #AAAAAA");
else
setStyle("");
来源:https://stackoverflow.com/questions/45067838/javafx-list-view-coloring-the-list-cell