具有突出显示文本(标签)的JavaFX表,性能较差 [英] JavaFX Table with highlighted text (Labels) with poor performance

查看:169
本文介绍了具有突出显示文本(标签)的JavaFX表,性能较差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要突出显示表中的部分文本我正在标记它并告诉列渲染器拆分文本并在标签<中呈现它/ code>总结为 HBox 。不幸的是性能很差。当显示> 400行时,它变得非常慢。我怎样才能加快速度?

To highlight parts of text in a Table i'm tagging it and tell a column renderer to split the text and render it in Labels summed up in a HBox. Unfortunately the performance is poor. When displaying > 400 lines its becoming very slow. How can i speed it up?

我使用以下代码突出显示中带有<$ c的文本$ c> HBoxes 包含多个标签。但是一些标签显示省略号而不是文本。如何强制标签以全宽显示?

Im using the following code to highlight text in a Table with HBoxes containing multiple Labels. But some Labels display ellipses instead of text. How can i force the Labels to appear in full width?

    ObservableList<TraceLine> items = FXCollections.observableArrayList();
    for (int i = 0; i < lines.size(); i++) {
        items.add(new TraceLine(i + startLineNumber + 1, lines.get(i)));
    }

    final TableColumn col1 = new TableColumn("#");
    col1.setCellValueFactory(new PropertyValueFactory<TraceLine, Integer>("lineNumber"));
    final TableColumn col2 = new TableColumn("Trace");
    col2.setCellValueFactory(new PropertyValueFactory<RegexMatch, String>("trace"));
    col2.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();
                        hbox.setAlignment(Pos.CENTER_LEFT);
                        String str = (String) text;
                        if (txtHighlight.getText().length() > 3 && str.contains(MainController.HIGHLIGHT_START)) {
                            // Something to highlight
                            hbox.getChildren().clear();
                            while (str.contains(MainController.HIGHLIGHT_START)) {
                                // First part
                                Label label = new Label(str.substring(0, str.indexOf(MainController.HIGHLIGHT_START)));
                                hbox.getChildren().add(label);
                                str = str.substring(str.indexOf(MainController.HIGHLIGHT_START) + MainController.HIGHLIGHT_START.length(), str.length());
                                // Part to highlight
                                Label label2 = new Label(str.substring(0, str.indexOf(MainController.HIGHLIGHT_END)));
                                label2.setStyle("-fx-background-color: " + MainController.HIGHLIGHT_COLOR + ";");
                                hbox.getChildren().add(label2);
                                // Last part
                                str = str.substring(str.indexOf(MainController.HIGHLIGHT_END) + MainController.HIGHLIGHT_END.length(), str.length());
                                if (!str.contains(MainController.HIGHLIGHT_START)) {
                                    Label label3 = new Label(str);
                                    hbox.getChildren().add(label3);
                                }
                            }
                        } else if (txtHighlight.getText().length() < 1) {
                            // Remove former highlightings and show simple text
                            str = str.replaceAll(MainController.HIGHLIGHT_START, "");
                            str = str.replaceAll(MainController.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;
        }
    });
    tableLines.getColumns().clear();
    tableLines.getColumns().addAll(col1, col2);
    tableLines.setItems(items);


推荐答案

为了我的解决方案,你需要移动一些零件周围。特别是搜索和拆分的逻辑应该移出渲染器,因为它不是真正与GUI相关的工作。

For my solution to work you need to move some parts around. Especially the logic of searching and splitting should be moved out of the Renderer as it is not really GUI related work..

因此,我们假设您的TableView具有以下数据类(其中dataNumber和dataString)只是其他TableColumns的随机属性:

So lets assume the following data class for your TableView (where dataNumber and dataString) are just random properties of other TableColumns:

public class MyTableData {

private final IntegerProperty dataNumber = new SimpleIntegerProperty(this, "dataNumber");
private final StringProperty dataString = new SimpleStringProperty(this, "dataString");

private String temporarySearch = null;
private ObjectProperty<List<String>> searchMatches = null;

public ObjectProperty<List<String>> searchMatchesProperty() {
    if(searchMatches == null) {
        searchMatches = new SimpleObjectProperty<>(this, "searchMatches");
        doSearch();
    }
    return searchMatches;
}

public List<String> getSearchMatches() {
    if(searchMatches == null) {
        return Collections.emptyList(); // or return null
    }
    return searchMatchesProperty().get();
}

public void setSearchMatches(List<String> pSearchMatches) {
    searchMatchesProperty().set(pSearchMatches);
}

public void search(String pSearchTerm) {
    temporarySearch = pSearchTerm;
    doSearch();
}

private void doSearch() {
    if(temporarySearch != null && searchMatches != null) {
        //TODO perform the search and split here, putting the search match fragments as
        // List<String> to setSearchMatches(List)
    }
}
}

有趣的部分是 searchMatches 属性,只有在调用 searchMatchesProperty()时才会初始化该属性。
任何对 search(String)的调用只存储搜索项,但在属性初始化之前不会执行任何实际逻辑。

The interesting part is the searchMatches property which only gets initialized if searchMatchesProperty() is called. Any calls to search(String) only store the search term but won't do any actual logic until the property is intialized.

在Cell Renderer中,您将调用 List< String> fragments = MyTableData.getSearchMatches();
如果列表为空或为空(换句话说:属性未初始化),则不显示任何内容,将搜索结果的单元格留空。或者因为没有匹配搜索词或因为属性没有初始化。

In your Cell Renderer you will call List<String> fragments = MyTableData.getSearchMatches();. If the list is empty or null (in other words: the property is not intialized) nothing to display, leaving your cell for the search results empty. Either because nothing matched the search term or because the property is not initialized.

现在到ValueFactory:
searchResultColumn.setCellValueFactory(p - > p.getValue()。firstNameProperty());
TableView足够智能,不会将每个值都浸泡到内存中,而只会覆盖当前正在显示的值。因此,当其单元格变为可见时,您的搜索结果属性将被初始化。因此,您的CellRenderer应该少花些多少工作,只渲染必要的部分。

Now to the ValueFactory: searchResultColumn.setCellValueFactory(p -> p.getValue().firstNameProperty()); The TableView is intelligent enough to not soak every value into memory, but only those which are currently being displayed. So your search result property gets initialized when its cell becomes visible. As a result your CellRenderer should have much less work, rendering only the necessary parts.

这篇关于具有突出显示文本(标签)的JavaFX表,性能较差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆