【问题标题】:setDisable() inside DatePicker's setDayCellFactory not working if HijrahChronology is set如果设置了 HijrahChronology,则 DatePicker 的 setDayCellFactory 中的 setDisable() 不起作用
【发布时间】:2015-03-07 11:51:53
【问题描述】:

我正在尝试使用 JavaFX 8 的 DatePicker 来禁用不在 [今天,今天 + 1 年] 范围内的日期,类似于 the example in the official tutorial。代码如下:

sample.fxml:

<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.DatePicker?>
<GridPane fx:controller="sample.Controller"
          xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">

    <DatePicker fx:id="dpDate"/>

</GridPane>

Main.java:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }


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

Controller.java:

package sample;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.util.Callback;
import javafx.util.StringConverter;

import java.net.URL;
import java.time.LocalDate;
import java.time.chrono.HijrahChronology;
import java.time.format.DateTimeFormatter;
import java.util.ResourceBundle;

public class Controller implements Initializable
{
    private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");

    @FXML private DatePicker dpDate;

    @Override
    public void initialize(URL location, ResourceBundle resources)
    {
        Callback<DatePicker, DateCell> dayCellFactory = dp -> new DateCell()
        {
            @Override
            public void updateItem(LocalDate item, boolean empty)
            {
                super.updateItem(item, empty);

                if(item.isBefore(LocalDate.now()) || item.isAfter(LocalDate.now().plusYears(1)))
                {
                    setStyle("-fx-background-color: #ffc0cb; -fx-text-fill: darkgray;");
                    setDisable(true);
                }
            }
        };

        StringConverter converter = new StringConverter<LocalDate>()
        {
            @Override
            public String toString(LocalDate date)
            {
                if(date != null) return dateFormatter.format(date);
                else return "";
            }

            @Override
            public LocalDate fromString(String string)
            {
                if(string != null && !string.isEmpty())
                {
                    LocalDate date = LocalDate.parse(string, dateFormatter);

                    if(date.isBefore(LocalDate.now()) || date.isAfter(LocalDate.now().plusYears(1)))
                    {
                        return dpDate.getValue();
                    }
                    else return date;
                }

                return null;
            }
        };

        dpDate.setDayCellFactory(dayCellFactory);
        dpDate.setConverter(converter);
        dpDate.setPromptText("dd/MM/yyyy");
        dpDate.setValue(LocalDate.now());
        dpDate.setChronology(HijrahChronology.INSTANCE);
    }
}


仅当我删除最后一行 dpDate.setChronology(HijrahChronology.INSTANCE); 并将其保留为默认值 IsoChronology 时,此示例才有效(即用户无法选择超出范围)。


我已经尝试消费updateItem()中的点击事件:

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

    if(item.isBefore(LocalDate.now()) || item.isAfter(LocalDate.now().plusYears(1)))
    {
        setStyle("-fx-background-color: #ffc0cb; -fx-text-fill: darkgray;");
        setDisable(true);

        addEventFilter(MouseEvent.MOUSE_CLICKED, e -> e.consume());
    }
}

它适用于当月(不能选择今天之前的日子)。但是如果我去接下来的几个月,它会阻止用户从允许的范围内选择一天。


这绝对是一个错误。有解决方法吗?如何访问日期选择器弹出窗口?也许我可以在更改月份页面的按钮上附加一个侦听器,然后遍历所有 say 单元格并手动禁用超出范围的日期。

【问题讨论】:

    标签: java javafx datepicker javafx-8 javafx-datepicker


    【解决方案1】:

    我在JavaFX JIRA 提交了一个错误报告,他们将在下次更新 8u60 时修复它。这是 Leif Samuelsson 建议的解决方法:

    这是 com.sun.javafx.scene.control.skin.DatePickerHijrahContent 中的一个错误。在 super 对自定义单元工厂调用 updateItem() 之后,它会覆盖 updateDayCells() 并在所有单元上调用 setDisable(false)。

    一种解决方法是将 setDisable() 调用包装在 Platform.runLater() 中:

    Platform.runLater(() -> { setDisable(true); });

    【讨论】:

    • 你能提供一个错误报告的公共链接吗?您已经提供的链接请求身份验证。
    • @OrtomalaLokni AFAIK,没有公共链接。您必须注册(而且它是免费的)才能访问它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-08
    相关资源
    最近更新 更多