I need to have TableView CELL should display text in multi line in single cell with multi color.
In CELL I am displaying Multiline text using \"\\n\" currently. But
You can use a custom cell factory in this case, here is an example:
TableView holding two TableColumns, one for the fullname and the second for the address of a Person instance.I've then set the cellFactory as follows:
addressCol.setCellFactory(column->{
return new TableCell<Person, String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if(item==null || empty) {
setGraphic(null);
} else {
VBox vbox = new VBox();
List<String> textList = Arrays.asList(item.split("\n"));
String[] colors = {"#3E50B4", "#FF3F80", "#727272"};
int colorCount = colors.length;
for(int i=0;i<textList.size();i++) {
Label lbl = new Label(textList.get(i));
lbl.setStyle("-fx-text-fill: "+colors[i%colorCount]);
vbox.getChildren().add(lbl);
}
setGraphic(vbox);
}
}
};
});
Now this is just an example where I've used a VBox containing a bunch of Label instances (one for each line), and I've hard coded the colors, you can use whatever you like, for example, you can try a TextFlow with Text nodes and you can also use CSS Style classes.
Here is the full example code:
TableViewExample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<VBox alignment="CENTER" spacing="10.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Label text="Colored Lines of Text in a Table Cell Example">
<font>
<Font size="16.0" />
</font>
</Label>
<TableView fx:id="personTable" prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn fx:id="fullnameCol" prefWidth="75.0" text="Full Name" />
<TableColumn fx:id="addressCol" prefWidth="75.0" text="Address" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</VBox>
Person.java
public class Person {
private String fullname, address;
public Person() {}
public Person(String fullname, String address) {
this.fullname = fullname;
this.address = address;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
MainApp.java
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MainApp extends Application implements Initializable {
@FXML private TableView<Person> personTable;
@FXML private TableColumn<Person, String> fullnameCol, addressCol;
ObservableList<Person> persons = FXCollections.observableArrayList();
public static void main(String [] args) {
launch(args);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
Person p1 = new Person("John Doe", "Charlotte ,\n403 St. Tryon Street");
Person p2 = new Person("Riyad Mahrez", "xxxxx, \n007 St.YYYY");
persons.addAll(p1, p2);
fullnameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("fullname"));
addressCol.setCellValueFactory(new PropertyValueFactory<Person, String>("address"));
addressCol.setCellFactory(column->{
return new TableCell<Person, String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if(item==null || empty) {
setGraphic(null);
} else {
VBox vbox = new VBox();
List<String> textList = Arrays.asList(item.split("\n"));
String[] colors = {"#3E50B4", "#FF3F80", "#727272"};
int colorCount = colors.length;
for(int i=0;i<textList.size();i++) {
Label lbl = new Label(textList.get(i));
lbl.setStyle("-fx-text-fill: "+colors[i%colorCount]);
vbox.getChildren().add(lbl);
}
setGraphic(vbox);
}
}
};
});
personTable.setItems(persons);
}
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("TableViewExample.fxml"));
loader.setController(this);
Parent parent = loader.load();
Scene scene = new Scene(parent);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I hope this helps...
You can use a cellFactory to customize the way the content is displayed. Assuming the values for the column are Strings like "Charlotte\n403 St. Tryon Street" and "Tony Stark\n10880 Malibu Point\n90265"
It could be done like this:
column.setCellFactory(tv -> new TableCell<MyItemType, String>() {
private final VBox lines;
{
lines = new VBox();
lines.getStyleClass().add("address");
setGraphic(lines);
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
lines.getChildren().clear();
if (!empty && item != null) {
int lineNo = 1;
for (String line : item.split("\n")) {
Text text = new Text(line);
text.getStyleClass().add("line-" + (lineNo++));
lines.getChildren().add(text);
}
}
}
});
.address > * {
-fx-fill: green;
}
.address > .line-1 {
-fx-fill: red;
}
Note that this uses CSS to style the lines, but you could also assign the color in the updateItem method directly...