410013796724260
• Webmoney
R335386147728
Z369087728698
в помощь разработчикам Swing-приложений
Пример компонента JDatePickerВ статье рассмотрен пример (example-datepicker) использования компонента JDatePicker модуля base-gui, позволяющего выбирать дату из выпадающего календаря. В основе компонента лежит код, созданный Juan Heyns. Доработанный компонент локализован для русского, английского и немецкого языков, позволяет определить первый день недели [Воскресенье, Понедельник]. На следующем скриншоте представлен интерфейс примера. В примере рассмотрены следующие возможности API компонента JDatePicker модуля base-gui :
Описание примераПример включает класс ExampleDatePicker, который будет представлен в статье следующим образом :
1. Описание полей классаОписание полей класса ExampleDatePicker включает метки lblFilter, lblFrom и lblTo, компоненты даты dtFrom и dtTo, константы (модификаторы final не приведены в листинге) определения надписей кнопок управления FIRST_DAY, FIRST_DAYS, LOCALIZATION, CHOOSE. Объекты локализации locale (текущий) и locales (возможные), идентификаторы первого дня недели FIRST_DAY_IDX и текущей локализации LOCALE_idx. Константа PATTERN_DATE определяет формат представления даты в интерфейсе примера. Константа SPAN_normal определяет порядок представления надписей на кнопках. JLabel lblFilter = null; JLabel lblFrom = null; JLabel lblTo = null; JDatePickerImpl dtFrom = null; JDatePickerImpl dtTo = null; String[] FIRST_DAY = {"Неделя с <%s>", "Week from <%s>", "Woche ab <%s>"}; String[][] FIRST_DAYS = {{"Вс", "По"}, {"Su", "Mo"}, {"Mo", "So"}}; String[] LOCALIZATION = {"Локализация" , "Localization" , "Lokalisierung"}; String[] CHOOSE = {"Выбор" , "Choose" , "Auswahl" }; Locale locale = null; Locale[] locales = {new Locale("ru"), new Locale("en"), new Locale("de")}; int FIRST_DAY_IDX = 0; int LOCALE_idx = 0; String PATTERN_DATE = "dd.MM.yyyy"; String SPAN_normal = "<html><span style=\"font-weight:normal\">"; 2. Формирование интерфейсаМетод createGUI формирует интерфейс примера. Особый интерес в коде данного метода представляют строки создания двух компонентов JDatePicker :
Примечание : обратите внимание, что для компонентов используются разные модели дат (UtilDateModel, UtilCalendarModel). private void createGUI() { JPanel pnlFilter = new JPanel(); pnlFilter.setLayout(new BorderLayout()); pnlFilter.setPreferredSize(new Dimension(268, 80)); Border border = BorderFactory.createCompoundBorder( BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(15, 10, 15, 4)); pnlFilter.setBorder(border); lblFilter = new JLabel(); lblFilter.setText(SPAN_normal + "Период времени"); // Определение параметров компонентов дат UtilDateModel modelFrom ; UtilCalendarModel modelTo ; JDatePanelImpl datePanelFrom; JDatePanelImpl datePanelTo ; DateLabelFormatter dlf ; modelFrom = new UtilDateModel (); modelTo = new UtilCalendarModel(); datePanelFrom = new JDatePanelImpl(modelFrom, locale); datePanelTo = new JDatePanelImpl(modelTo , locale); dlf = new DateLabelFormatter(PATTERN_DATE); //----------------------------------------------------- Dimension dim = new Dimension(100, 20); Dimension dimLabel = new Dimension( 30, 20); //----------------------------------------------------- lblFrom = new JLabel(); lblFrom.setText(SPAN_normal + "c"); lblFrom.setPreferredSize(dimLabel); dtFrom = new JDatePickerImpl(datePanelFrom, dlf); dtFrom.setPreferredSize(new Dimension(145, 20)); dtFrom.getJFormattedTextField().setBackground(Color.WHITE); SpringLayout layoutFilter = new SpringLayout(); JPanel pnlFrom = new JPanel(layoutFilter); pnlFrom.add(lblFrom); pnlFrom.add(dtFrom); pnlFrom.setPreferredSize(dim); pnlFrom.setSize (dim); layoutFilter.putConstraint(SpringLayout.WEST, dtFrom, 30, SpringLayout.EAST, lblFrom); //----------------------------------------------------- lblTo = new JLabel(); lblTo.setText(SPAN_normal + "по"); lblTo.setPreferredSize(dimLabel); dtTo = new JDatePickerImpl(datePanelTo, dlf); dtTo.setPreferredSize(new Dimension(145, 20)); dtTo.getJFormattedTextField().setBackground(Color.WHITE); JPanel pnlTo = new JPanel(layoutFilter); pnlTo.add(lblTo); pnlTo.add(dtTo); pnlTo.setPreferredSize(dim); pnlTo.setSize (dim); layoutFilter.putConstraint(SpringLayout.WEST, dtTo, 30, SpringLayout.EAST, lblTo); //----------------------------------------------------- pnlFilter.add(pnlFrom, BorderLayout.NORTH); pnlFilter.add(pnlTo , BorderLayout.SOUTH); //----------------------------------------------------- String caption = SPAN_normal + String.format(FIRST_DAY[LOCALE_idx], FIRST_DAYS[LOCALE_idx][FIRST_DAY_IDX]); JButton btnFirstDay = new JButton(caption); String caption = SPAN_normal + LOCALIZATION[LOCALE_idx]; JButton btnLocale = new JButton(caption); String caption = SPAN_normal + CHOOSE[LOCALE_idx]; JButton btnFilter = new JButton(caption); final int WIDTH_BUTTON = 130; dim = new Dimension (WIDTH_BUTTON, 28); btnFirstDay.setPreferredSize(dim); btnLocale .setPreferredSize(dim); btnFilter .setPreferredSize(dim); // Панель кнопок управления JPanel pnlButtons = new JPanel(); pnlButtons.add(btnFirstDay); pnlButtons.add(btnLocale ); pnlButtons.add(btnFilter ); btnFirstDay.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { changeFirstWeekDay(); String caption = SPAN_normal + String.format(FIRST_DAY[LOCALE_idx], FIRST_DAYS[LOCALE_idx][FIRST_DAY_IDX]); btnFirstDay.setText(caption); } }); btnLocale.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { changeLocale(); btnLocale .setText(SPAN_normal + LOCALIZATION[LOCALE_idx]); btnFilter .setText(SPAN_normal + CHOOSE[LOCALE_idx]); btnFirstDay.setText(SPAN_normal + String.format(FIRST_DAY[LOCALE_idx], FIRST_DAYS[LOCALE_idx][FIRST_DAY_IDX])); } }); btnFilter.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { ChoosedDates(); } }); getContentPane().add(lblFilter , BorderLayout.NORTH ); getContentPane().add(pnlFilter , BorderLayout.CENTER); getContentPane().add(pnlButtons, BorderLayout.SOUTH); } Обработчики нажатий кнопок управления вызывают методы изменения первого дня недели и текущего языка локализации, вывода сообщения с выбранными датами. 3. Определение первого дня неделиИсходный код компонента JDatePicker, созданный Juan Heyns, допускает только один вариант первого дня недели «Su» (Sunday). Модифицированный компонент JDatePicker модуля base-gui позволяет выбрать первым днём недели как «Понедельник» (Monday), так и «Воскресенье» (Sunday). Для изменения текущего первого дня недели перезагрузки компонента не требуется, достаточно вызвать метод компонента setFirstDayMonday (boolean); истинное значение параметра (true) определяет первый день недели «Понедельник» (Monday). Ниже представлен листинг метода changeFirstWeekDay, который динамически в режиме run-time изменяет первый день недели в окне календаря. private void changeFirstWeekDay() { if (++FIRST_DAY_IDX == 2) FIRST_DAY_IDX = 0; dtFrom.setFirstDayMonday (!dtFrom.isFirstDayMonday()); dtTo.setFirstDayMonday (!dtTo .isFirstDayMonday()); } На следующем скриншоте представлен открытый календарь компонента с первым днем недели «По» (Понедельник). На скриншоте описания локализации (см. скриншот ниже) представлено окно календаря с первым днём недели «Su» (Sunday/Воскресенье). 4. ЛокализацияЛокализация в примере касается только наименований кнопок и выпадающего окна календаря. Модифицированный компонент JDatePicker модуля base-gui позволяет использовать один из 3-х языков локализации : [русский (по умолчанию), английский, немецкий]. Для переключения языка локализации не требуется перезагрузка компонента, достаточно вызвать метод компонента changeLocale с объектом локализации, например changeLocale(new Locale("ru")). Ниже представлен листинг метода changeLocale, который динамически в режиме run-time изменяет язык локализации окна раскрывающегося календаря. private void changeLocale() { if (++LOCALE_idx >= locales.length) LOCALE_idx = 0; dtFrom.changeLocale(locales[LOCALE_idx]); dtTo .changeLocale(locales[LOCALE_idx]); } На скриншоте описания первого дня недели (см.скриншот выше) представлена русскоязычная версия открытого календаря. На следующем скриншоте представлен раскрытый календарь в английской интерпретации : окно выбора месяца, надписи и дни недели представлены на английском языке. 5. Чтение значенийМетод ChoosedDates формирует сообщение с выбранными датами и отображает его в диалоговом окне JOptionPane главного JFrame. Для получения значения даты следует использовать метод getValue модели данных (getModel()) компонента. Если значение даты не определено/выбрано, то метод вернет 'null'. Примечание : поскольку компоненты дат (dtFrom, dtTo) используют разные модели(UtilDateModel и UtilCalendarModel), то имеются и существенные отличия получения выбранного значения даты. private void ChoosedDates() { // Выбранные строки String msg = "Вы выбрали период с '%s' по '%s'"; String title = "Выбор"; String from = "null"; String to = "null"; SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); if (dtFrom.getModel().getValue() != null) from = sdf.format(dtFrom.getModel().getValue()); if ((dtTo.getModel() instanceof UtilDateModel) && (dtTo.getModel().getValue() != null)) to = sdf.format(dtTo.getModel().getValue()); else if ((dtTo.getModel() instanceof UtilCalendarModel) && (dtTo.getModel().getValue() != null)) { Calendar calendar; calendar = (Calendar) dtTo.getModel().getValue(); to = sdf.format(calendar.getTime()); } msg = String.format(msg, from, to); JOptionPane.showMessageDialog (ExampleDatePicker.this, msg, title, JOptionPane.INFORMATION_MESSAGE); } На следующем скриншоте представлено окно с сообщением. 6. Главный класс ExampleDatePickerЛистинг класса ExampleDatePicker (см. код ниже), не включает поля и методы, описанные выше. Полный исходный код примера можно скачать в конце страницы. В конструкторе класса определяется текущий язык локализации и вызывается метод создания интерфейса. public class ExampleDatePicker extends JFrame { public ExampleDatePicker() { super("Form example"); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(440, 180); locale = locales[LOCALE_idx]; createGUI(); vsetVisible(true); } public static void main(String[] args) { new ExampleDatePicker(); } } Привязка выпадающего календаря к правому/левому краю компонентаНа представленных выше скриншотах видно, что размер компонента по горизонтали меньше ширины открытого календаря. При этом, окно календаря привязано к левой стороне компонента. Исходный JDatePicker, созданный Juan Heyns, не допускал привязку окна календаря к правой стороне компонента при его близком размещении к правой стороне экрана; в этом случае часть календаря не отображалась на экране. Единственным спасением в этом случае было определять ширину компонента не меньше ширины окна календаря. Доработанный JDatePicker модуля base-gui автоматически привязывает всплывающее окно календаря к правому краю компонента при его близком расположении к правой стороне монитора. Чтобы увидеть это достаточно переместить мышью окно примера в правую часть монитора и открыть окно календаря, как это представлено на следующем скриншоте. Старт примераАрхив примера включает командный файл run-example-datepicker.bat для старта example-datepicker.jar в Windows из командной строки. Запускаемый example-datepicker.jar (runable) может быть стартован не только из командной строки, но и обычным способом (двойным нажатием клавишей мыши), поскольку модуль lib/base-gui-1.0.0.jar включен в classpath манифеста META-INF/MANIFEST.MF. Скачать примерАрхивный файл base-gui-example.zip включает данный пример (example-datepicker) и другие примеры использования модуля base-gui. |