java – 内容显示在具有自定义单元工厂的空行中

如果行value.setCellFactory(NUMBER_CELL_FACTORY);下面的程序工作正常;被注释掉了.

但是,如果包含它,TableView表现得很奇怪* – 如果您只是复制代码,启动它并在按钮上单击几次,您将看到内容出现在表格底部的空行中.

我错过了什么吗?

*在JavaFx 8上测试 – b106.

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
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.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TestFX extends Application {

    @Override
    public void start(final Stage stage) throws Exception {
        MyTable table = new MyTable();

        Scene scene = new Scene(table);

        stage.setScene(scene);
        stage.show();
    }

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

    static class MyTable extends AnchorPane {

        private static final Callback NUMBER_CELL_FACTORY = (p) -> new NumberTableCell<>();

        private final Button addRow = new Button("+");
        private final TableView<Item> table = new TableView<>();

        MyTable() {
            super();
            initTableView();
            addRow.setOnMouseClicked((e) -> addItem());
            VBox vbox = new VBox();
            vbox.getChildren().addAll(addRow, table);
            getChildren().add(vbox);
        }

        public void addItem() {
            table.getItems().addAll(new Item());
        }

        private void initTableView() {
            TableColumn<Item, Double> value = new TableColumn<>("Value");
            value.setCellValueFactory(new PropertyValueFactory<>("value"));
            value.setCellFactory(NUMBER_CELL_FACTORY);

            table.getColumns().add(value);
            table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        }
    }

    public static class Item {
        private final DoubleProperty value = new SimpleDoubleProperty();

        public DoubleProperty valueProperty() {
            return value;
        }
    }

    static class NumberTableCell<T> extends TableCell<T, Double> {
        private final Color fill = Color.LIGHTGREY;

        @Override
        protected void updateItem(Double item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) return;
            setText(String.valueOf(item));
            setTextFill(fill);
        }
    }
}
最佳答案
我在Win7 Java7b108上尝试了你的示例程序,它似乎与NumberTableCell一起正常工作,但它仍有问题.

问题是单元格被重用,因此如果单元格由于任何原因变空,则需要清除在单元格中设置的任何自定义值,以使其呈现为默认的空单元格.下面的代码演示了如何执行此操作:

    @Override
    protected void updateItem(Double item, boolean empty) {
        super.updateItem(item, empty);
        if (empty || item == null) {
            setText(null);
            setTextFill(null);
            return;
        }
        setText(String.valueOf(item));
        setTextFill(fill);
    }

这是对您的程序的一个小更新,更容易复制问题并演示修复.如果你注释掉setText(null)和setTextFill(null)行,然后按下按钮几次,然后开始按 – 按钮,你会看到TableView没有真正反映底层列表的状态.但是在那里使用null设置器,一切都正确同步.这是一个问题……

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TestFX extends Application {

    @Override
    public void start(final Stage stage) throws Exception {
        MyTable table = new MyTable();

        System.getProperties().list(System.out);

        Scene scene = new Scene(table);

        stage.setScene(scene);
        stage.show();
    }

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

    static class MyTable extends AnchorPane {

        private static final Callback NUMBER_CELL_FACTORY = (p) -> new NumberTableCell<>();

        private final Button addRow = new Button("+");
        private final Button removeRow = new Button("-");
        private final TableView<Item> table = new TableView<>();

        MyTable() {
            super();
            initTableView();
            addRow.setOnMouseClicked((e) -> addItem());
            removeRow.setOnMouseClicked((e) -> removeItem());
            VBox vbox = new VBox(5);
            vbox.getChildren().addAll(addRow, removeRow, table);
            getChildren().add(vbox);
        }

        public void addItem() {
            table.getItems().addAll(new Item());
        }

        public void removeItem() {
            if (table.getItems().size() > 0) {
                table.getItems().remove(0);
            }
        }

        private void initTableView() {
            TableColumn<Item, Double> value = new TableColumn<>("Value");
            value.setCellValueFactory(new PropertyValueFactory<>("value"));
            value.setCellFactory(NUMBER_CELL_FACTORY);

            table.getColumns().add(value);
            table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        }
    }

    public static class Item {
        private final DoubleProperty value = new SimpleDoubleProperty();

        public DoubleProperty valueProperty() {
            return value;
        }
    }

    static class NumberTableCell<T> extends TableCell<T, Double> {
        private final Color fill = Color.LIGHTGREY;

        @Override
        protected void updateItem(Double item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || item == null) {
                setText(null);
                setTextFill(null);
                return;
            }
            setText(String.valueOf(item));
            setTextFill(fill);
        }
    }
}

转载注明原文:java – 内容显示在具有自定义单元工厂的空行中 - 代码日志