在JavaFX中创建行索引列[英] Creating a row index column in JavaFX

问题描述

我有一个Javafx tableview,我正在使用一个observablists的任务.我一直在尝试创建一个显示每行索引的列,该列是表中任务的ID,但是我尝试了方法此处以及其他成功来源的类似方法.

我的参考代码,没有表面错误(据Eclipse所知):

    @FXML private TableColumn<Task, String> taskIndexCol;
    Callback<TableColumn<Task, String>, TableCell<Task, String>> cb =
            new Callback<TableColumn<Task, String>, TableCell<Task, String>>(){
                @Override
                public TableCell<Task, String> call(TableColumn<Task, String> col) {
                    TableCell<Task, String> cell = new TableCell<Task, String>() {
                        @Override
                        protected void updateItem(String item, boolean empty) {
                            super.updateItem(item, empty);
                            if (item == null) {
                                setText("");
                            } else {
                                setText(getIndex()+"");
                            }
                        }
                    };
                    return cell;
                }
    };

    taskIndexCol.setCellFactory(cb);

当前,当我尝试设置列的细胞效应时,我的代码为我提供了NullPoInterException.我已经尝试使用填充的任务列表,但这无济于事.我已经度过了很长时间 - 从理论上讲,这应该很容易,因为它只是编号行?感觉就像我正在跳过一百万个篮球,做一些令人沮丧的事情.

编辑:最后一行给我NPE.

推荐答案

不可能说出无效指针异常的原因,因为您尚未显示堆栈跟踪,识别了抛出异常的行或张贴了足够的代码(您的回调中的任何代码都不可以抛出无效的指针异常,所以其他地方出了问题).

对于实际的单元格实现,您没有在列上显示cellValueFactory设置.如果您不这样做,那么item将始终 be null,因此您永远不会在该列中的单元格中看到任何文本.您可以检查empty属性(或方法参数),以作为检查单元格是否在空行中或具有实际数据的手段. (请注意,这意味着该列确实根本不需要提供任何数据:可以是TableColumn<Task, Void>.)

此外,使用updateIndex(...)而不是updateItem(...)可能更安全.当索引更改时,保证updateIndex被调用;如果您实现updateItem,则假设在项目之前设置了索引,这意味着您依靠实现细节.

如果使用Java 8 lambda表达式,您的代码短得多,并且更容易阅读:

taskIndexCol.setCellFactory(col -> new TableCell<Task, String>() {
    @Override
    protected void updateIndex(int index) {
        super.updateIndex(index);
        if (isEmpty() || index < 0) {
            setText(null);
        } else {
            setText(Integer.toString(index));
        }
    }
});

或替代

taskIndexCol.setCellFactory(col -> {
    TableCell<Task, String> cell = new TableCell<>();
    cell.textProperty().bind(Bindings.when(cell.emptyProperty())
        .then("")
        .otherwise(cell.indexProperty().asString()));
    return cell ;
});

这是SSCCE:

import java.util.function.Function;

import static javafx.beans.binding.Bindings.when ;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TableViewWithIndexColumn extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Person> table = new TableView<>();
        table.setEditable(true);

        table.getItems().addAll(
                new Person("Jacob", "Smith", "jacob.smith@example.com"),
                new Person("Isabella", "Johnson",
                        "isabella.johnson@example.com"),
                new Person("Ethan", "Williams", "ethan.williams@example.com"),
                new Person("Emma", "Jones", "emma.jones@example.com"),
                new Person("Michael", "Brown", "michael.brown@example.com"));


        TableColumn<Person, String> firstNameCol = createColumn("First Name",
                Person::firstNameProperty, 150);
        TableColumn<Person, String> lastNameCol = createColumn("Last Name",
                Person::lastNameProperty, 150);
        TableColumn<Person, String> emailCol = createColumn("Email",
                Person::emailProperty, 150);

        // index column doesn't even need data...
        TableColumn<Person, Void> indexCol = createColumn("Index", person -> null, 50);

        // cell factory to display the index:
//        indexCol.setCellFactory(col -> {
//            
//            // just a default table cell:
//            TableCell<Person, Void> cell = new TableCell<>();
//            
//            cell.textProperty().bind(
//                when(cell.emptyProperty())
//                    .then("")
//                    .otherwise(cell.indexProperty().asString()));
//            
//            return cell ;
//        });

        indexCol.setCellFactory(col -> new TableCell<Person, Void>() {
            @Override
            public void updateIndex(int index) {
                super.updateIndex(index);
                if (isEmpty() || index < 0) {
                    setText(null);
                } else {
                    setText(Integer.toString(index));
                }
            }
        });

        table.getColumns().add(indexCol);
        table.getColumns().add(firstNameCol);
        table.getColumns().add(lastNameCol);
        table.getColumns().add(emailCol);

        primaryStage.setScene(new Scene(new BorderPane(table), 600, 400));
        primaryStage.show();
    }

    private <S, T> TableColumn<S, T> createColumn(String title,
            Function<S, ObservableValue<T>> property, double width) {
        TableColumn<S, T> col = new TableColumn<>(title);
        col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
        col.setPrefWidth(width);
        return col;
    }

    public static class Person {
        private final StringProperty firstName = new SimpleStringProperty();
        private final StringProperty lastName = new SimpleStringProperty();
        private final StringProperty email = new SimpleStringProperty();

        public Person() {
            this("", "", "");
        }

        public Person(String firstName, String lastName, String email) {
            setFirstName(firstName);
            setLastName(lastName);
            setEmail(email);
        }

        public final StringProperty firstNameProperty() {
            return this.firstName;
        }

        public final java.lang.String getFirstName() {
            return this.firstNameProperty().get();
        }

        public final void setFirstName(final java.lang.String firstName) {
            this.firstNameProperty().set(firstName);
        }

        public final StringProperty lastNameProperty() {
            return this.lastName;
        }

        public final java.lang.String getLastName() {
            return this.lastNameProperty().get();
        }

        public final void setLastName(final java.lang.String lastName) {
            this.lastNameProperty().set(lastName);
        }

        public final StringProperty emailProperty() {
            return this.email;
        }

        public final java.lang.String getEmail() {
            return this.emailProperty().get();
        }

        public final void setEmail(final java.lang.String email) {
            this.emailProperty().set(email);
        }

    }

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

本文地址:https://www.itbaoku.cn/post/978619.html