JAVAFX TableView CELL should display text in multi

2020-03-30 02:57发布

问题:

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 I am not able to set color for each line in the same cell, for example text in the CELL is : Charlotte , 403 St. Tryon Street then I want In Single cell, Charlotte as first line and 403 St. Tryon Street as sencond line with Charlotte as RED color and remaining text on 2nd line as Green color.

回答1:

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);
            }
        }
    }

});

CSS stylesheet

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



回答2:

You can use a custom cell factory in this case, here is an example:

  • I've created an FXML document that contains a 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...



标签: html javafx cell