Статьи

JavaFX 8 DatePicker в приложении Swing

1. Обзор

В этой статье показан пример приложения Java SE 8 Swing, использующего DatePicker управления JavaFX 8 DatePicker .

DatePicker управления DatePicker позволяет пользователю вводить дату в виде текста или выбирать дату во всплывающем календаре. В этом примере используется Swing JFrame с элементами управления FX. Для встраивания содержимого FX в приложение javafx.embed.swing пакет javafx.embed.swing предоставляет класс JFXPanel .

Приложение берет введенную дату из средства выбора даты и проверяет, находится ли оно в выбранном пользователем диапазоне дат (от и до даты) из двух средств выбора даты. Проверка даты выбора даты включает в себя:

  • Дата от меньше даты
  • Даты не из будущего
  • Дата ввода находится в пределах от и до даты (включая)

Недопустимые или действительные сообщения отображаются в диалоговых окнах FX Alert .

На следующих двух FXPanel экрана показано приложение с JFrame и встроенными элементами управления FX ( FXPanel с DatePicker , DatePicker и Button ) и DatePicker календарем DatePicker соответственно.

FX контролирует в Swing JFrame

FX контролирует в Swing JFrame

FX DatePicker с всплывающим календарем

FX DatePicker с всплывающим календарем

1.1. Исходный код

Исходный код для этого примера FXDatePickerInSwingExample.java доступен для загрузки по ссылке, приведенной в конце этой статьи. Обратите внимание, что Java SE 8 требуется для компиляции и запуска кода. Java SE 8 включает в себя JavaFX 8.

2. Описание приложения

Приложение Java Swing FXDatePickerInSwingExample запускается из метода main() программы Java SE в потоке диспетчеризации событий следующим образом:

1
2
3
SwingUtilities.invokeLater(() -> {
    new FXDatePickerInSwingExample().initAndShowGUI();
});

Метод initAndShowGUI() отображает Swing JFrame со встроенными в него элементами управления JavaFX. Следующий фрагмент кода показывает конструкцию JFrame :

1
2
3
4
JFrame frame = new JFrame("JavaFX DatePicker in Swing App");
JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setVisible(true);

javafx.embed.swing.JFXPanel является компонентом для встраивания содержимого JavaFX в приложения Swing и обеспечивает совместимость JavaFX и Swing. JFXPanel расширяет JFXPanel javax.swing.JComponent . Отображаемый контент указывается с помощью JFXPanel setScene() который принимает экземпляр javafx.scene.Scene . Этот метод вызывается в потоке диспетчеризации событий приложения FX следующим образом:

1
2
3
Platform.runLater(() -> {
    fxPanel.setScene(createScene());
});

Метод createScene() возвращает экземпляр Scene с элементами управления FX. Скриншоты, показанные выше, имеют законченный графический интерфейс. В следующем фрагменте кода показан метод createScene() с фрагментами кода:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private Scene createScene() {
     
    GridPane grid = new GridPane();
         
    // Title
    Label title1 = new Label("Enter and check if the input date is");
    Label title2 = new Label("within the selected date range.");
    VBox titleVb = new VBox();
    titleVb.setAlignment(Pos.CENTER);
    titleVb.getChildren().addAll(title1, title2);
         
    // Input date picker
    Label inPickLabel = new Label("Input date:");
    inPicker = new DatePicker();
    inPicker.setPromptText(pattern);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
    StringConverter converter = new LocalDateStringConverter(formatter, null);
    inPicker.setConverter(converter);
    grid.add(inPickLabel, 0, 0);
    grid.add(inPicker, 1, 0);
 
    // From and to date pickers
    Label pickLabel1 = new Label("From date:");
    fmPicker = new DatePicker(LocalDate.now());
    fmPicker.setEditable(false);
    grid.add(pickLabel1, 0, 1);
    grid.add(fmPicker, 1, 1);
    ...
 
    // Button
    ...
 
    // Vbox and scene
    VBox vbox = new VBox(20);
    vbox.setPadding(new Insets(15, 15, 15, 15));
    vbox.getChildren().addAll(titleVb, grid, btnHb);
 
    return new Scene(vbox);
}

2.1. Элемент управления DatePicker

javafx.scene.control.DatePicker управления javafx.scene.control.DatePicker позволяет пользователю вводить дату в виде текста или выбирать дату во всплывающем календаре. Свойство DatePicker представляет LocalDate выбранный LocalDate . Это свойство может использоваться с конструктором, а также имеет методы getValue() и setValue() .

Следующий фрагмент кода создает объект выбора даты и устанавливает его значение на сегодняшнюю дату: DatePicker picker = new DatePicker(LocalDate.now());

2.2. Проверка даты

В этом приложении есть три сборщика даты. Все они настроены на сбор действительных дат:

  • Значения даты не могут быть больше, чем сегодня.
  • Дата начала никогда не может быть после даты.

Для выполнения этих ограничений используется dayCellFactoryProperty DatePicker . Можно настроить собственную фабрику ячеек для настройки отдельных ячеек дня во всплывающем окне выбора даты. У средства выбора даты есть метод для установки фабрики пользовательских ячеек: setDayCellFactory() .

Эти API используются для создания собственной фабрики ячеек: класс DateCell используется DateCell даты для визуализации отдельных ячеек сетки в календарном месяце. Приложение может переопределить метод update DateCell чтобы изменить свойства каждой ячейки, такие как текст, цвет фона и т. Д.

В следующем фрагменте кода показан метод, который возвращает пользовательский dayCellFactory . Обратите внимание, что этот единственный метод возвращает фабрику ячеек для трех сборщиков дат.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private Callback getCustomDateCellFactory(DateParameterType dateParamType) {
     
    Callback dayCellFactory = new Callback() {
     
        @Override
        public DateCell call(DatePicker datePicker) {
         
            return new DateCell() {
             
                @Override
                public void updateItem(LocalDate select, boolean b) {
                 
                    super.updateItem(select, empty);
                         
                    // Date cannot be after today.
                    // This applies for all the date pickers.
                    if (select.isAfter(LocalDate.now())) {
 
                        setDisable(true);
                        return;
                    }
 
                    // From-date cannot be greater than to-date.
                    if ((dateParamType == DateParameterType.FROM_DATE)
                            &&
                            (select.isAfter(toPicker.getValue()))) {
 
                        setDisable(true);
                    }
                         
                    // To-date cannot be less than from-date,
                    // and cannot be greater than today.
                    if (dateParamType == DateParameterType.TO_DATE) {
                         
                        if ((select.isBefore(fmPicker.getValue())) ||
                                (select.isAfter(LocalDate.now()))) {
 
                        setDisable(true);
                         }
                     }
        ...
    };
         
    return dayCellFactory;
}

Этот пользовательский dayCellFactory применяется к средствам dayCellFactory даты в createScene() следующим образом:

1
2
3
inPicker.setDayCellFactory(getCustomDateCellFactory(null));
fmPicker.setDayCellFactory(getCustomDateCellFactory(DateParameterType.FROM_DATE));
toPicker.setDayCellFactory(getCustomDateCellFactory(DateParameterType.TO_DATE));

Метод getCustomDateCellFactory() приложения возвращает фабрику пользовательских ячеек, getCustomDateCellFactory() выше. Параметр метода DateParameterType enum идентифицирует DateParameterType даты, для которого применяется фабрика ячеек. Например, средство выбора даты требует даты выбора текущей даты, чтобы получить ячейки, которые должны быть отключены; поэтому DateParameterType.FROM используется для идентификации соответствующего фрагмента кода (см. следующий фрагмент кода).

1
2
3
4
5
// From-date cannot be greater than to-date.
if ((dateParamType == DateParameterType.FROM_DATE) &&
        (select.isAfter(toPicker.getValue()))) {
    setDisable(true);
}

2,3. Пользовательский конвертер для ввода даты

По умолчанию средство выбора даты показывает строку даты в шаблоне (например, дд / мм / гггг) в соответствии с конвертером по умолчанию. Это можно переопределить, предоставив специальный преобразователь в DatePicker setConverter() . Выбор даты ввода принимает и показывает дату в формате, отличном (dd-MMM-yy) от формата по умолчанию, используя пользовательский конвертер. Следующее примечание показывает использование пользовательского конвертера.

Эти API используются для создания пользовательского конвертера в этом примере:

Создайте StringConverter для значений LocalDate используя предоставленные LocalDate форматирования и анализатор. Форматтер используется для преобразования даты в форматированную строку с использованием указанного шаблона. Обратите внимание, что парсер указан как ноль. Этот конвертер применяется к входному DatePicker dd-MMM-yy . При выборе из всплывающего окна дата отображается в формате dd-MMM-yy с помощью конвертера.

Следующий фрагмент кода показывает создание и использование конвертера:

1
2
3
4
String pattern = "dd-MMM-yy";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
StringConverter converter = new LocalDateStringConverter(formatter, null);
picker.setConverter(converter);

2,4. LocalDate

Java.time.LocalDate — это дата в календарной системе ISO-8601 (современная гражданская календарная система, используемая сегодня в большинстве стран мира), например, 2007-12-03. В этом классе не хранится информация о времени или часовом поясе. Экземпляр может быть создан из года, месяца и дня с использованием статического метода LocalDate.of(int year, int month, int dayOfMonth) .

Ниже приведены API, используемые в этом приложении:

  • LocalDate.now() получает текущую дату из системных часов в часовом поясе по умолчанию. Это статический метод.
  • isAfter(ChronoLocalDate localDate) проверяет, находится ли эта дата после указанной даты. Это проверяет, представляет ли эта дата точку на местной временной шкале после другой даты. LocalDate реализует интерфейс java.time.chrono.ChronoLocalDate .
  • isBefore(ChronoLocalDate localDate) проверяет, isBefore(ChronoLocalDate localDate) ли эта дата указанной дате.
  • isEqual(ChronoLocalDate localDate) проверяет, равна ли эта дата указанной дате.

Следующая процедура используется в примере, чтобы проверить, находится ли введенная дата в выбранном диапазоне дат. Входные данные, а также выбранные даты и даты получены из DatePicker управления DatePicker . DatePicker getValue() LocalDate возвращает объект LocalDate .

01
02
03
04
05
06
07
08
09
10
11
private boolean validDate(LocalDate start, LocalDate end, LocalDate input) {
    if ((input.isEqual(start)) || (input.isEqual(end))) {
        return true;
    }
    else if ((input.isAfter(start)) && (input.isBefore(end))) {
        return true;
    }
    else {
        return false;
    }
}

3. Оповещения

Это ссылка на статью, описывающую диалоги javafx.scene.control.Alert используемые в этом примере.

4. Пример использования

Java Swing не имеет компонента выбора даты. Используя технику, показанную в этом примере, приложение Swing может использовать DatePicker управления DatePicker FX в DatePicker Swing JFrame . Например, этот JFrame может быть диалоговым окном функции «Поиск по дате», где можно выбрать диапазон дат, а входные данные (например, коллекция счетов) можно искать по их датам в пределах выбранного диапазона дат.

Окно приложения Swing может открыть это диалоговое окно JFrame в качестве немодального окна, когда пользователь нажимает кнопку «Поиск по дате» actionPerformed() метод actionPerformed() кнопки actionPerformed() создает экземпляр этого диалога «Поиск по дате»).

5. Скачать исходный код

Это был пример JavaFX 8 DatePicker in Swing Application

Скачать
Вы можете скачать полный исходный код этого примера здесь: FXDatePickerInSwingExample.zip

*