JavaFX 2刷新表格单元以更改样式 [英] JavaFX 2 refresh table cell to change style

查看:93
本文介绍了JavaFX 2刷新表格单元以更改样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在具有可变列数的TableView中更改任意单元格的样式.下面的代码显示了基本问题.

I need to change the style of arbitrary cells in a TableView which has an variable number of columns. The code below shows the basic problem.

ExampleRow类是来自电子表格的真实数据的代理,它的另一个功能是保存突出显示的信息.因为我不知道会有多少列,所以我只保留应突出显示的列列表(不支持列重新排列). ExampleTableCell类仅设置单元格的文本,并在需要时应用突出显示.

The ExampleRow class is proxy for the real data which comes from a spreadsheet, it's other function is to hold the highlighting information. Since I can't know how many columns there will be I just hold a list of columns that should be highlighted (column re-arrangement won't be supported). The ExampleTableCell class just sets the text for the cell and applies the highlight if needed.

如果我在绘制表格[cell(2,2)]之前设置了突出显示,那么当应用程序启动时,该单元格将正确显示为红色文本.问题是单击按钮会将单元格(1,1)设置为突出显示,但表格不会更改.如果我将应用程序窗口的大小调整为没有大小,然后再次打开它,则将正确绘制单元格(1,1)的突出显示-大概是因为此过程会强制进行完全重绘.

If I set a highlight before the table gets drawn [cell (2,2)] then the cell correctly gets displayed with red text when the application starts. The problem is clicking the button sets cell (1,1) to be highlighted but the table doesn't change. If I resize the application window to nothing then open it back up again the highlighting of cell (1,1) is correctly drawn - presumably because this process forces a full redraw.

我想知道的是如何触发表格重新绘制新突出显示的单元格(或所有可见的单元格),以便样式正确?

What I would like to know is how can I trigger the table to redraw newly highlighted cells (or all visible cells) so the styling is correct?

TIA

package example;

import java.util.HashSet;
import java.util.Set;
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;

public class CellHighlightExample extends Application {

    private final int columnCount = 4;
    private final int rowCount = 5;
    private TableView<ExampleRow> table = new TableView<>();

    @Override
    public void start(Stage stage) {
        BorderPane root = new BorderPane();
        Scene scene = new Scene(root);

        Callback<TableColumn.CellDataFeatures<ExampleRow, String>, ObservableValue<String>> cellValueFactory = new Callback<TableColumn.CellDataFeatures<ExampleRow, String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<ExampleRow, String> p) {
                int row = p.getValue().getRow();
                int col = p.getTableView().getColumns().indexOf(p.getTableColumn());
                return new SimpleObjectProperty<>("(" + row + ", " + col + ")");
            }
        };

        Callback<TableColumn<ExampleRow, String>, TableCell<ExampleRow, String>> cellFactory = new Callback<TableColumn<ExampleRow, String>, TableCell<ExampleRow, String>>() {
            @Override
            public TableCell<ExampleRow, String> call(TableColumn<ExampleRow, String> p) {
                return new ExampleTableCell<>();
            }
        };

        for (int i = 0, n = columnCount; i < n; i++) {
            TableColumn<ExampleRow, String> column = new TableColumn<>();
            column.setCellValueFactory(cellValueFactory);
            column.setCellFactory(cellFactory);
            table.getColumns().add(column);
        }

        ObservableList<ExampleRow> rows = FXCollections.observableArrayList();
        for (int i = 0, n = rowCount; i < n; i++) {
            ExampleRow row = new ExampleRow(i);
            //Force a cell to be highlighted to show that highlighting works.
            if (i == 2) { row.addHighlightedColumn(2); }
            rows.add(row);
        }
        table.setItems(rows);

        Button b = new Button("Click to Highlight");
        b.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                ExampleRow row = table.getItems().get(1);
                row.addHighlightedColumn(1);
                //How to trigger a redraw of the table or cell to reflect the new highlighting?
            }
        });

        root.setTop(b);
        root.setCenter(table);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    private class ExampleTableCell<S extends ExampleRow, T extends String> extends TableCell<S, T> {

        @Override
        public void updateItem(T item, boolean empty) {
            super.updateItem(item, empty);

            if (item == null) {
                setText(null);
                setGraphic(null);
            } else {
                setText(item);
                int colIndex = getTableView().getColumns().indexOf(getTableColumn());
                ExampleRow row = getTableView().getItems().get(getIndex());
                if (row.isHighlighted(colIndex)) {
                    setTextFill(Color.RED);
                }
            }
        }
    }

    private class ExampleRow {

        private SimpleIntegerProperty row;
        private Set<Integer> highlightedColumns = new HashSet<>();

        public ExampleRow(int row) {
            this.row = new SimpleIntegerProperty(row);
        }

        public int getRow() { return row.get(); }
        public void setRow(int row) { this.row.set(row); }
        public SimpleIntegerProperty rowProperty() { return row; }

        public boolean isHighlighted(int col) {
            if (highlightedColumns.contains(col)) {
                return true;
            }
            return false;
        }

        public void addHighlightedColumn(int col) {
            highlightedColumns.add(col);
        }
    }
}

推荐答案

对此问题有很多讨论,即在更改项目后刷新表视图.
请参阅
JavaFX 2.1 TableView刷新项
问题
http://javafx-jira.kenai.com/browse/RT-21822
http://javafx-jira.kenai.com/browse/RT-22463
http://javafx-jira.kenai.com/browse/RT-22599

There are lots of discussions about this problem, namely refreshing tableview after altering the item(s).
See
JavaFX 2.1 TableView refresh items
Issues
http://javafx-jira.kenai.com/browse/RT-21822
http://javafx-jira.kenai.com/browse/RT-22463
http://javafx-jira.kenai.com/browse/RT-22599

解决方案是触发内部tableview更新方法.有些人建议删除tableview项,然后再次添加它们.但是,针对您的案例,最简单的解决方法似乎是:

The solution is to trigger internal tableview update method. Some suggests to remove tableview items and add them again vs.. but the simplest workaround for your case seems to:

b.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent t) {
        ExampleRow row = table.getItems().get(1);
        row.addHighlightedColumn(1);
        //How to trigger a redraw of the table or cell to reflect the new highlighting?
        // Workaround
        table.getColumns().get(0).setVisible(false);
        table.getColumns().get(0).setVisible(true);
    }
});

其中发现了上面链接的问题评论.这是真的解决方法还是错觉?您需要更深入地挖掘自己.

which found in issue comments linked above. Is this a really workaround or illusion of it? You need to dig deeper yourself.

这篇关于JavaFX 2刷新表格单元以更改样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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