JAVAFX-具有可修改custum时间选择器单元格的Tableview关闭过快

JAVAFX-具有可修改custum时间选择器单元格的Tableview关闭过快,javafx,tableview,timepicker,Javafx,Tableview,Timepicker,我有一个可修改的custum TimePicker单元格的表视图。 我写了一个函数来监听单元格中的变化,但是当我点击一个特定的小时时,时钟不会在第一次点击时保持打开和关闭,我必须再次点击以选择分钟为例。 当时钟关闭时,如何让时钟打开并使EditCommitteEvent()生效 谢谢你的帮助:) 这是我的客户电话号码。 PS:我使用jfoenix时间选择器 public class TimePickerTableCell<Patient> extends TableCell<P

我有一个可修改的custum TimePicker单元格的表视图。 我写了一个函数来监听单元格中的变化,但是当我点击一个特定的小时时,时钟不会在第一次点击时保持打开和关闭,我必须再次点击以选择分钟为例。 当时钟关闭时,如何让时钟打开并使EditCommitteEvent()生效

谢谢你的帮助:)

这是我的客户电话号码。 PS:我使用jfoenix时间选择器

public class TimePickerTableCell<Patient> extends TableCell<Patient, LocalTime> {

    private JFXTimePicker timePicker;
    private boolean listening = true;

    // listener for changes in the timePicker
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private final ChangeListener<LocalTime> listener = (observable, oldValue, newValue) -> {
        if (listening) {
            listening = false;

            TableColumn<Patient, LocalTime> column = getTableColumn();
            EventHandler<TableColumn.CellEditEvent<Patient, LocalTime>> handler = column.getOnEditCommit();

            if (handler != null) {
                // use TableColumn.onEditCommit if there is a handler

                handler.handle(new TableColumn.CellEditEvent<>(
                        (TableView<Patient>) getTableView(),
                        new TablePosition<Patient, LocalTime>(getTableView(), getIndex(), column),
                        TableColumn.<Patient, LocalTime>editCommitEvent(),
                        newValue
                        ));             

            } else {
                // otherwise check if ObservableValue from cellValueFactory is
                // also writable and use in that case
                ObservableValue<LocalTime> observableValue = column.getCellObservableValue((Patient) getTableRow().getItem());
                if (observableValue instanceof WritableValue) {
                    ((WritableValue) observableValue).setValue(newValue);
                }
            }
            listening = true;
        }
    };

    public TimePickerTableCell () {
        this.timePicker = new JFXTimePicker();
        this.timePicker.valueProperty().addListener(listener);

        this.timePicker.setOnMouseEntered((event)->{timePicker.requestFocus();timePicker.show();System.err.println("OUVERTURE TIMEPICKER");});
        this.timePicker.setOnMouseExited((event)->{if(event.getY()<23)timePicker.hide();});
    }

    @Override
    protected void updateItem(LocalTime item, boolean empty) {
        super.updateItem(item, empty);

        if (empty) {
            listening = false;
            setGraphic(null);
        } else {
            listening = false;
            setGraphic(this.timePicker);
            this.timePicker.setValue(item);
            this.timePicker.getStyleClass().add("time-picker");
            listening = true;
        }
    }

    public static <E> Callback<TableColumn<E, LocalTime>, TableCell<E, LocalTime>> forTableColumn() {
        return column -> new TimePickerTableCell<>();
    }

}
公共类TimePickerTableCell扩展了TableCell{
专用JFXTimePicker定时器选择器;
私有布尔监听=真;
//计时器选择器中更改的侦听器
@SuppressWarnings({“unchecked”,“rawtypes”})
私有最终ChangeListener侦听器=(可观察、旧值、新值)->{
如果(听){
倾听=错误;
TableColumn=getTableColumn();
EventHandler=column.getOnEditCommit();
if(处理程序!=null){
//如果存在处理程序,请使用TableColumn.onEditCommit
handler.handle(新建TableColumn.CellEditEvent(
(TableView)getTableView(),
新表位置(getTableView(),getIndex(),column),
TableColumn.EditCommitteEvent(),
新价值
));             
}否则{
//否则,检查cellValueFactory的ObservalEvalue是否为
//也可写,并在该情况下使用
ObservableValue ObservableValue=column.getCellObservableValue((患者)getTableRow().getItem());
if(observableValue实例of WritableValue){
((WritableValue)observeValue).setValue(newValue);
}
}
倾听=真实;
}
};
公共时间选择器表单元格(){
this.timePicker=新的JFXTimePicker();
this.timePicker.valueProperty().addListener(listener);
this.timePicker.setOnMouseEntered((事件)->{timePicker.requestFocus();timePicker.show();System.err.println(“OUVERTURE timePicker”);});
this.timePicker.setOnMouseExited((事件)->{if(event.getY()new TimePickerTableCell();
}
}

首先,当您点击时钟时,
JFXTimePicker
隐藏的原因(很可能)是因为您的
onMouseExited
处理程序。当您将鼠标移动到弹出窗口上时,它“退出”了
JFXTimePicker
,从而隐藏了时钟

您还以错误的方式实现了一个可编辑的
TableCell
。您应该重写类的和方法(该类继承自
TableCell
)。您可以查看类的源代码,比如它是如何实现的。我还制作了一个使用
JFXTimePicker
执行此操作的示例:

import com.jfoenix.controls.JFXTimePicker;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.input.KeyCode;
import javafx.util.Callback;
import javafx.util.converter.LocalTimeStringConverter;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class TimePickerTableCell<S> extends TableCell<S, LocalTime> {

    // Static methods for creating TableColumn.cellFactory Callbacks

    public static <S> Callback<TableColumn<S, LocalTime>, TableCell<S, LocalTime>> forTableColumn() {
        return v -> new TimePickerTableCell<>();
    }

    public static <S> Callback<TableColumn<S, LocalTime>, TableCell<S, LocalTime>> forTableColumn(DateTimeFormatter formatter) {
        return v -> new TimePickerTableCell<>(formatter);
    }

    // Formatter property

    private final ObjectProperty<DateTimeFormatter> formatter = new SimpleObjectProperty<>(this, "formatter");
    public final void setFormatter(DateTimeFormatter formatter) { this.formatter.set(formatter); }
    public final DateTimeFormatter getFormatter() { return formatter.get(); }
    public final ObjectProperty<DateTimeFormatter> formatterProperty() { return formatter; }

    // JFXTimePicker field

    private JFXTimePicker timePicker;

    // Constructors

    public TimePickerTableCell() {
        this(DateTimeFormatter.ISO_LOCAL_TIME);
    }

    public TimePickerTableCell(DateTimeFormatter formatter) {
        getStyleClass().add("time-picker-table-cell");
        setFormatter(formatter);
    }

    // Display logic

    @Override
    protected void updateItem(LocalTime item, boolean empty) {
        super.updateItem(item, empty);

        setGraphic(null);

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

    private String formatItem(LocalTime item) {
        if (item == null) {
            return null;
        }
        return getFormatter() == null ? item.toString() : getFormatter().format(item);
    }

    // Edit logic

    @Override
    public void startEdit() {
        if (!isEditable() ||
                !getTableColumn().isEditable() ||
                !getTableView().isEditable()) {
            return;
        }
        super.startEdit();
        if (isEditing()) {
            if (timePicker == null) {
                createTimePicker();
            }
            timePicker.setValue(getItem());
            setText(null);
            setGraphic(timePicker);

            // Wrapped this in a Platform#runLater call because otherwise
            // I couldn't get this to work properly. Despite this, there are
            // times where this still seems buggy.
            Platform.runLater(() -> {
                timePicker.requestFocus();
                timePicker.getEditor().selectAll();
            });
        }
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        setText(formatItem(getItem()));
        setGraphic(null);
    }

    private void createTimePicker() {
        timePicker = new JFXTimePicker();

        timePicker.setConverter(new LocalTimeStringConverter(getFormatter(), null));
        formatter.addListener((observable, oldValue, newValue) ->
                timePicker.setConverter(new LocalTimeStringConverter(newValue, null)));

        timePicker.getEditor().setOnKeyReleased(event -> {
            if (event.getCode() == KeyCode.ENTER) {
                commitEdit(timePicker.getValue());
                event.consume();
            } else if (event.getCode() == KeyCode.ESCAPE) {
                cancelEdit();
                event.consume();
            }
        });

        timePicker.focusedProperty().addListener((observable, oldValue, newValue) -> {
            if (!newValue) {
                cancelEdit();
            }
        });

    }
}
import com.jfoenix.controls.JFXTimePicker;
导入javafx.application.Platform;
导入javafx.beans.property.ObjectProperty;
导入javafx.beans.property.SimpleObject属性;
导入javafx.scene.control.TableCell;
导入javafx.scene.control.TableColumn;
导入javafx.scene.input.KeyCode;
导入javafx.util.Callback;
导入javafx.util.converter.LocalTimeStringConverter;
导入java.time.LocalTime;
导入java.time.format.DateTimeFormatter;
公共类TimePickerTableCell扩展了TableCell{
//用于创建TableColumn.cellFactory回调的静态方法
forTableColumn()的公共静态回调{
返回v->新建TimePickerTableCell();
}
表列的公共静态回调(DateTimeFormatter格式化程序){
返回v->新建TimePickerTableCell(格式化程序);
}
//格式化程序属性
私有最终ObjectProperty格式化程序=新的SimpleObjectProperty(此“格式化程序”);
公共最终void setFormatter(DateTimeFormatter格式化程序){this.formatter.set(formatter);}
公共最终日期TimeFormatter getFormatter(){return formatter.get();}
公共最终ObjectProperty formatterProperty(){return formatter;}
//JFXTimePicker字段
专用JFXTimePicker定时器选择器;
//建设者
公共时间选择器表单元格(){
这是(DateTimeFormatter.ISO_本地时间);
}
公共TimePickerTableCell(DateTimeFormatter格式化程序){
getStyleClass().add(“时间选择器表单元格”);
设置格式化程序(格式化程序);
}
//显示逻辑
@凌驾
受保护的void updateItem(LocalTime项,布尔值为空){
super.updateItem(项,空);
设置图形(空);
if(空| |项==null){
setText(空);
}否则{
setText(格式项(项目));
}
}
私有字符串格式项(LocalTime项){
如果(项==null){
返回null;
}
返回getFormatter()==null?item.toString():getFormatter().format(item);
}
//编辑逻辑
@凌驾
公开作废已启动IT(){
如果(!isEditable()||
!getTableColumn().isEditable()||
!getTableView().isEditable()){
返回;
}
super.startEdit();
if(isEditing()){
if(timePicker==null){
createTimePicker();
}
setValue(getItem());
setText(空);
设定图形(时间选择器);
//将其包装在平台#runLater调用中,因为否则
//我不能让它正常工作。尽管如此,还是有
//这似乎还是有问题的时候。
Platform.runLater(()->{
timePicker.requestFocus();
timePicker.getEditor().selectAll();
});
}
}
@凌驾
公共作废取消编辑(){
super.cancelEdit();
setText(formatItem(getItem());
设置图形(空);
}
私有void createTimePicker(){
timePicker=新的JFXTimePicker