JavaFX TableView with highlighted text

alex

I want to highlight parts of text displayed in a JavaFX TableView. Till now i'm using Text objects in TextFlow objects. To highlight specific parts in a text i am using tags to cut the text in parts (javafx.scene.text objects) to highlight or not to highlight with the following code.

col3.setCellValueFactory(new PropertyValueFactory<RegexMatch, String>("text"));
col3.setCellFactory(new Callback<TableColumn, TableCell>() {
    @Override
    public TableCell call(TableColumn param) {
        TableCell cell = new TableCell() {
            @Override
            protected void updateItem(Object text, boolean empty) {
                if (text != null && text instanceof String) {
                    String str = (String) text;
                    TextFlow flow = new TextFlow();
                    if (txtSearchField.getText().length() > 3 && str.contains(HIGHLIGHT_START)) {
                        // Something to highlight
                        flow.getChildren().clear();
                        while (str.contains(HIGHLIGHT_START)) {
                            // First part
                            Text starttext = new Text(str.substring(0, str.indexOf(HIGHLIGHT_START)));
                            starttext.setWrappingWidth(Double.MAX_VALUE);
                            flow.getChildren().add(starttext);
                            str = str.substring(str.indexOf(HIGHLIGHT_START) + HIGHLIGHT_START.length(), str.length());
                            // Part to highlight
                            Text highlightedText = new Text(str.substring(0, str.indexOf(HIGHLIGHT_END)));
                            highlightedText.setStyle("-fx-text-background-color: yellow;");
                            highlightedText.setFill(Color.BLUE);
                            highlightedText.setWrappingWidth(Double.MAX_VALUE);
                            flow.getChildren().add(highlightedText);
                            // Last part
                            str = str.substring(str.indexOf(HIGHLIGHT_END) + HIGHLIGHT_END.length(), str.length());
                            if (!str.contains(HIGHLIGHT_START)) {
                                Text endtext = new Text(str);
                                endtext.setWrappingWidth(Double.MAX_VALUE);
                                flow.getChildren().add(endtext);
                            }
                        }
                    }else if (txtSearchField.getText().length() < 1) {
                        // Remove former highlightings and show simple text
                        str = str.replaceAll(HIGHLIGHT_START, "");
                        str = str.replaceAll(HIGHLIGHT_END, "");
                        flow.getChildren().clear();
                        Text textModule = new Text(str);
                        textModule.setWrappingWidth(Double.MAX_VALUE);
                        flow.getChildren().add(textModule);
                    } else {
                        // show simple text
                        flow.getChildren().clear();
                        Text textModule = new Text(str);
                        textModule.setWrappingWidth(Double.MAX_VALUE);
                        flow.getChildren().add(textModule);
                    }
                    flow.setPrefHeight(bigIcons ? BIG_SIZE : SMALL_SIZE);
                    setGraphic(flow);
                }
            }
        };
        return cell;
    }
});

Unfortunately the background highlighting does not work and i have strange linebreaks as shown in the picture. The text does not contain any linebreaks.

scrennshot oft table

(Sorry for the picture quality, its a real screenshot :))

Any help is appreciated.

Solution
As @eckig suggested, using multiple Labels in a HBox is an good idea, because each 'Label' can have its own background color and you can use as much Labels in line in a HBox as needed:

  col3.setCellValueFactory(new PropertyValueFactory<RegexMatch, String("excerptLineTable"));
  col3.setCellFactory(new Callback<TableColumn, TableCell>() {
    @Override
    public TableCell call(TableColumn param) {
        TableCell cell = new TableCell() {
            @Override
            protected void updateItem(Object text, boolean empty) {
                if (text != null && text instanceof String) {
                    HBox hbox = new HBox();


                    String str = (String) text;
                    if (txtSearchField.getText().length() > 3 && str.contains(HIGHLIGHT_START)) {
                        // Something to highlight
                        hbox.getChildren().clear();
                        while (str.contains(HIGHLIGHT_START)) {
                            // First part
                            Label label = new Label(str.substring(0, str.indexOf(HIGHLIGHT_START)));
                            hbox.getChildren().add(label);
                            str = str.substring(str.indexOf(HIGHLIGHT_START) + HIGHLIGHT_START.length(), str.length());
                            // Part to highlight
                            Label label2 = new Label(str.substring(0, str.indexOf(HIGHLIGHT_END)));
                            label2.setStyle("-fx-background-color: blue;");
                            hbox.getChildren().add(label2);
                            // Last part
                            str = str.substring(str.indexOf(HIGHLIGHT_END) + HIGHLIGHT_END.length(), str.length());
                            if (!str.contains(HIGHLIGHT_START)) {
                                Label label3 = new Label(str);
                                hbox.getChildren().add(label3);
                            }
                        }
                    } else if (txtSearchField.getText().length() < 1) {
                        // Remove former highlightings and show simple text
                        str = str.replaceAll(HIGHLIGHT_START, "");
                        str = str.replaceAll(HIGHLIGHT_END, "");
                        hbox.getChildren().clear();
                        Label label = new Label(str);
                        hbox.getChildren().add(label);
                    } else {
                        // show simple text
                        hbox.getChildren().clear();
                        Label label = new Label(str);
                        hbox.getChildren().add(label);
                    }
                    setGraphic(hbox);
                }
            }
        };
        return cell;
    }
});
eckig

After double reading your problem I think we can resume this as follows:

  • A rather long text in a TableColumn
  • The user should be able to filter this text
  • Each text-fragment which matches the current search term is to be highlighted.

Now you have two options:

  1. Create a HBox and add Labels containg the text fragments. A Label extends Region and so may have a background color.
  2. Use TextFlow and add Texts as text fragments. There you can "only" change the foreground color.

Ah and before I forget: To disable TextFlow text wrapping you must not call textModule.setWrappingWidth(Double.MAX_VALUE); but instead textModule.setPrefWidth(Double.MAX_VALUE);

And another hint: Try to recycle as much as possible. Recreating the whole TextFlow on each update is not really a good idea (instead store it as member variable in the cell).

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

JavaFX Table with highlighted text (Labels) with poor performance

From Dev

How to detect a selection on JavaFX TableView when clicking a highlighted item?

From Dev

JavaFX : Coloring TableView row and formatting the cell text

From Dev

JavaFX 8 - How to bind TextField text property to TableView integer property

From Dev

javafx - How to set selected row text color in not focused TableView

From Dev

JavaFX - TableView - Populate cell with text from multiple properties

From Dev

Wrap highlighted text in Pycharm

From Dev

script for focusing on a highlighted text

From Dev

Wrap highlighted text in Pycharm

From Dev

Send with a form the highlighted text (jquery)

From Dev

Text and Image Highlighted same time

From Dev

Vim - select text highlighted by search?

From Dev

Text and Image Highlighted same time

From Dev

Prefix/Suffix highlighted text in textbox

From Dev

Green Highlighted Text in Word 2016

From Dev

Access highlighted text from script?

From Dev

Styling a TableView in CSS (JavaFX)

From Dev

colspan and rowspan for tableview in JavaFX

From Dev

ComboBox in a tableview cell in JavaFX

From Dev

JavaFX property adapter for TableView

From Dev

JavaFX TableView Objects with Maps

From Dev

Javafx TableView Edit Validation

From Dev

JavaFX Spinner Editor in TableView

From Dev

JavaFX Properties in TableView

From Dev

JavaFX Derby TableView

From Dev

JavaFX TableView with Transaction Support

From Dev

JavaFX TableView Sort Policy

From Dev

TableView data encoding in JavaFX

From Dev

Binding Chart to TableView JavaFX