-
Bug
-
Resolution: Fixed
-
P4
-
8u31, 8u40
-
Windows 8.1 Pro 64bit - JDK 8 u40
Ref: http://stackoverflow.com/q/28914579/597657
I am trying to use JavaFX 8's DatePicker with disabling the days that are not in the range [today, today + 1 year], similar to [the example in the official tutorial][1]. Here is the code:
**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);
}
}
![enter image description here][2]
---
This example works (i.e. user cannot select out of the range) only if I remove the last line `dpDate.setChronology(HijrahChronology.INSTANCE);` and leave it with default `IsoChronology`.
![enter image description here][3]
---
I have tried to consume the click event inside `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());
}
}
It works on the current month (the days before today cannot be selected). But if I go to the next months, it prevents the user from selecting a day from the permitted range.
---
Definitely this is a bug. Is there a workaround? How can I access the date picker popup? Maybe I can attach a listener to the button that change the month page, and then iterate over all the say cells and disable the out-of-range days manually.
[1]: http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/date-picker.htm#CCHEBIFF
[2]: http://i.stack.imgur.com/tapAW.png
[3]: http://i.stack.imgur.com/7BZwM.png
I am trying to use JavaFX 8's DatePicker with disabling the days that are not in the range [today, today + 1 year], similar to [the example in the official tutorial][1]. Here is the code:
**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);
}
}
![enter image description here][2]
---
This example works (i.e. user cannot select out of the range) only if I remove the last line `dpDate.setChronology(HijrahChronology.INSTANCE);` and leave it with default `IsoChronology`.
![enter image description here][3]
---
I have tried to consume the click event inside `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());
}
}
It works on the current month (the days before today cannot be selected). But if I go to the next months, it prevents the user from selecting a day from the permitted range.
---
Definitely this is a bug. Is there a workaround? How can I access the date picker popup? Maybe I can attach a listener to the button that change the month page, and then iterate over all the say cells and disable the out-of-range days manually.
[1]: http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/date-picker.htm#CCHEBIFF
[2]: http://i.stack.imgur.com/tapAW.png
[3]: http://i.stack.imgur.com/7BZwM.png
- relates to
-
JDK-8115425 [DatePicker] Exception when Hijrah-umalqura chronology is used, and old data is set, breaks control
-
- Resolved
-