【问题标题】:Remove Datepicker rendering from a TableView cell (JavaFX8)从 TableView 单元格中删除 Datepicker 呈现 (JavaFX8)
【发布时间】:2017-10-19 14:07:01
【问题描述】:

我有一个包含 2 列“Date”(LocalDate)和“FX”(Double)的 TableView。我已启用单元格编辑,并按照我在此处找到的示例 (http://physalix.com/javafx8-render-a-datepicker-cell-in-a-tableview/) 创建了一个自定义 CellFactory,它为“日期”列的单元格显示 DatePicker。尽管此解决方案会立即呈现 DatePciker,但我将代码更改为仅在用户双击任何(非空)日期单元格时才显示 DatePicker。到目前为止一切顺利……

在用户更改日期或取消输入后,如何“返回”并从单元格中删除 DatePicker 渲染?请参阅图片作为参考。图 1 是列表的初始状态。图2是双击后。如何返回到图 1 状态?如果您需要查看我的具体代码,请告诉我。

Reference pictures

这是检查双击然后创建 CellFactory 的代码

 fxTable.getSelectionModel().setCellSelectionEnabled(true);
    fxTable.setOnMouseClicked(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            if (event.getClickCount() == 2) {
                TablePosition pos = fxTable.getSelectionModel().getSelectedCells().get(0);
                int col = pos.getColumn();
                if (col == 0) {

                    //The code below creates the DatePicker in the cell using the DatePickerCell class that I created following the example in the code I found
                    tblDateFX.setCellFactory(new Callback<TableColumn<Map.Entry<LocalDate, Double>, String>, TableCell<Map.Entry<LocalDate, Double>, String>>() {
                        @Override
                        public TableCell<Map.Entry<LocalDate, Double>, String> call(TableColumn<Map.Entry<LocalDate, Double>, String> param) {
                            ObservableMap<LocalDate, Double> items = FXCollections.observableMap(myBasket.getEnrtriesCur(curName));

                            DatePickerCell datePick = new DatePickerCell(items);
                            return datePick;
                        }
                    });
                }
            }
        }
    });

这是 DatePickerCell 类

public class DatePickerCell<S, T> extends TableCell<Map.Entry<LocalDate,Double>, String> {

private DatePicker datePicker;
private ObservableMap<LocalDate,Double> curEntries;


public DatePickerCell(ObservableMap<LocalDate,Double> curEntries) {

    super();

    this.curEntries = curEntries;

    if (datePicker == null) {
        createDatePicker();
    }
    setGraphic(datePicker);
    setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            datePicker.requestFocus();
        }
    });
}

@Override
public void updateItem(String item, boolean empty) {

    super.updateItem(item, empty);

    if (null == this.datePicker) {
        System.out.println("datePicker is NULL");
    }

    if (empty) {
        setText(null);
        setGraphic(null);
    } else {

        if (isEditing()) {

            setContentDisplay(ContentDisplay.TEXT_ONLY);

        } else {

            datePicker.setValue(LocalDate.parse(item,df));


            setGraphic(this.datePicker);
            setText(item);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

        }
    }
}

@Override
public void startEdit() {
    super.startEdit();
}

@Override
public void cancelEdit() {
    super.cancelEdit();
    setContentDisplay(ContentDisplay.TEXT_ONLY);
    setGraphic(null);
}


private void createDatePicker() {
    this.datePicker = new DatePicker();
    datePicker.setEditable(true);

    datePicker.setOnMouseClicked(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            setGraphic(datePicker);
            setText(df.format(datePicker.getValue()));
        }
    });

    datePicker.setOnAction(new EventHandler() {
        public void handle(Event t) {
            LocalDate date = datePicker.getValue();
            int index = getIndex();

            commitEdit(df.format(date));

            if (null != getCurEntries()) {
                System.out.println("Modify value");

            }
        }
    });

    setAlignment(Pos.CENTER);
}

【问题讨论】:

  • 请将您的代码添加到示例中,否则很难帮助您。
  • 您链接的代码质量很低。您可能想找到(或只是编写)单元的更好实现。
  • @James_D 我还是一个 Java 新手,很遗憾我自己无法编写那种代码,而且我找不到其他任何可行的方法。
  • @Gabriele TBH,没有人应该写那种代码。
  • @James_D 啊!很高兴知道! :) 我将在另一个问题中问什么是在单元格中呈现 DatePicker 的好代码。

标签: java datepicker tableview javafx-8


【解决方案1】:

您是否尝试过 setOnEditCommit 函数来反转您的代码?

column.setOnEditCommit((TableColumn.CellEditEvent<MyObject, Date> t) -> {
    //modify the rendering of you cell to normal
});

【讨论】:

  • 这可以工作,但至关重要的是,我如何将渲染修改回“正常”?我刚开始学习Java,所以我的知识有限。也许只是找出 tablecell 的默认呈现是什么,它是如何完成并调用它的?
【解决方案2】:

经过一番研究,我发现 TableView 中单元格的默认呈现是一个标签。因此,我调整了 DatePickerCell 类以在“updateItem”方法中呈现标签,并仅在单击标签时呈现 DatePicker(这意味着用户想要编辑单元格中的日期)。

就“返回”而言,我在 DatePicker 上为“ESC keypressed”添加了一个侦听器,因此当按下该键(在编辑期间)时,会呈现一个标签,因此会取消编辑。效果很好!

当用户试图通过单击屏幕上的其他位置来取消编辑时,我仍在尝试弄清楚如何做同样的事情。

--

所以这是我对 DatePickerEdit 课程的尝试。

这是做我需要的。首先正常渲染单元格,只有当用户单击日期单元格时才会渲染日期选择器。如果用户在单元格之外单击,则单元格将返回到其初始呈现状态(在编辑时按下“ESC”或确实选择了新日期时也会发生同样的情况)。

请注意,我将包含 TableView 中显示的值的 Observable 列表传递给类。这样我可以直接在类中更新列表中的值。不确定这是否是一个好习惯,但这是一个“强制解决方案”。最初我对 TableColumn 使用“setOnEditCommit”方法,但经过一些测试后,我注意到在更新单元格后并不总是调用此事件(即为单元格调用 commitEdit() 方法)。不确定这是错误还是我的代码有问题。当然,它并不总是发生。在多次运行中,我会说三分之一的人表现出这种错误行为。

这是代码,不确定它是否是“好”代码。我将不胜感激任何有价值的建议。

public class DatePickerCell<S, T> extends TableCell<FX, String> {

    private DatePicker datePicker;
    private Label lbl;
    private ObservableList<FX> currencies;


    public DatePickerCell(ObservableList<FX> list) {

        super();

        lbl=new Label();
        this.currencies=list;
        if (datePicker == null) {
            createDatePicker();
        }

    }

    @Override
    public void updateItem(String item, boolean empty) {
//        This section here manages the graphic rendering of each cell
//        As I don't want to generate the datepicker graphics immediately I just render a label
        super.updateItem(item, empty);

        if (empty || item == null) {
            setText(null);
            setGraphic(null);
        } else {
            createLabel(item);
        }
    }

    @Override
    public void startEdit() {
        super.startEdit();
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
    }

    private void createDatePicker() {
        this.datePicker = new DatePicker();
        datePicker.setEditable(true);

//        when the user clicks on the label the DatePicker graphics is generated
        lbl.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {

                datePicker.setValue(LocalDate.parse(lbl.getText(),df));
                setGraphic(datePicker);
                setText(lbl.getText());
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                datePicker.requestFocus();
            }
        });


//       This listener manages the "lost focus" on the picker
        datePicker.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
//                This combination of OldValue NewValue is generated whenever there is a click outside the DatePicker "graphic area"
//                i.e. the calendar (when open), the text filed, the calendar icon OR when a NEW date is selected in the calendar.
//                 This last case generates the "OnAction" event as well that is managed below.
                if (oldValue && !newValue) {
                    createLabel(df.format(datePicker.getValue()));
                }
            }
        });

//        This is generated when a NEW date is picked
//        it simply commits the new date and changes the graphics back to a label
        datePicker.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                LocalDate date = datePicker.getValue();
                int index=getIndex();

                if (date!=null) {
                    commitEdit(df.format(date));
                    getCurrencies().get(index).setDate(date);
                    createLabel(df.format(date));
                }
            }
        });

//        added this listener in case the user wants to cancel pressing "ESC"
//        when this happens the label graphics is rendered
        datePicker.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                LocalDate date = datePicker.getValue();
                if (event.getCode()== KeyCode.ESCAPE) {
                    createLabel(df.format(date));
                }
            }
        });

        setAlignment(Pos.CENTER_LEFT);
    }

    private void createLabel(String item) {
        lbl.setMinWidth(getWidth());
        setGraphic(lbl);
        lbl.setText(item);
    }

    public ObservableList<FX> getCurrencies() {
        return currencies;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多