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...