Zadání datumu pomocí Kalendáře v JavaFX
Poznámka na úvod: Podstatné jméno datum úmyslně skloňuji nespisovně podle mužského vzoru, tj. datum, datumu, datumem, apod. Jde mi vyloučení případné záměny se slovem data (ve smyslu soubor datových údajů).
Datum je jeden z nejdůležitějších datových typů používaných při vývoji a provozu aplikace. Přesné a příjemné zadání posiluje "positive user feeling".
Možností jak "pokazit" datum je celé řada - nesprávný oddělovač, nesprávná hodnota dne (závisí na hodnotě měsíce - leden má 31 dnů, únor 28 až 29 dnů, březen 31 dnů, …), nesprávná hodnota měsíce, 29. února je pouze v přestupném roce, atd.
Kalendář
Výhodnější je vybrat požadované datum z grafického Kalendáře. To by uživateli ulehčilo zadávání a zpříjemnilo práci. Pokud by požadoval zadání bez pomoci Kalendáře (například účetní, která raketovým tempem "láduje" aplikaci novými účetními doklady), tak bez problémů může. Jen nevyužije nabízenou možnost (kontrola na správnost zadaného datumu se provádí vždy). Tato možnost je dnes v aplikacích velice často rozšířena. Jak tento nástroj zakomponovat do Java aplikace?
Java má od verze 8 novou třídu pro práci datem: LocalDate (o novém API pro práci s časem si můžete přečíst v tomto článku). Dobře s ní spolupracuje třída DataPicker (JavaFX UI Controls - Kalendář je v této třídě implementován). Její metoda getvalue() vrací uživatelem vybrané datum typu LocalDate. Odpovídá standardu ISO-8601 (bez časové zóny). Jedná se vlastně o Gregoriánský kalendář proleptický (definován i pro datumy před jeho uvedením roku 1582).
Pro zobrazení kalendáře je nutné mít správně nastavený Locale - třída pro nastavení geografických, politických a kulturních specifik regionu. Nastavení regionu může být kritickou složkou vývoje v případě, že píšete aplikaci pro mezinárodní prostředí (internationalization of application). Může se například jednat o podnik, kde dělníci a střední managent jsou Češi. Vrcholový management jsou Američené, Němci, Francouzi, apod. Ani Číňané už nejsou výjimkou. V těchto případech musíte být schopni nastavit aplikaci tak, aby pro určitý okruh uživatelů pracovala v jejich mateřském jazyku. Region se nastavuje statickou metodou setdefault(newLocale). Regionu odpovídá vstupní parametr newLocale. Je možno ho zadat jako konstantu nebo LanguageTag
Konstanta
NetBeans Vám jich po stisku Ctrl+Space nabídne celou řadu. Uvedu jen pár příkladů:
Locale.setDefault(Locale.US);
Locale.setDefault(Locale.UK);
Locale.setDefault(Locale.PRC); (People Republic China)
U nastavení Locale.US si dovolím upozornit na skutečnost, že prvním dnem týdne je Neděle a posledním Sobota. Druhou odlišností oproti evropským kalendářům (například Locale.UK) je posloupnost kterou se datum čte. Na první pozici je měsíc, náleduje den a polední je rok.
LanguageTag
Použití jazykového tagu je nutné v případě, kdy požadovaný region není v okruhu běžně používaných konstant, kam patří také čeština. Seznam všech LanguageTags můžete nalézt na oficiálních webových stránkách
Lehce zjistíme náš LangugeTag: "cz-CS". Nastavení češtiny je pak:
Locale.setDefault(Locale.forLanguageTag("cs-CZ"));
Výhodou LanguageTag je, že s ním můžeme nastavit všechny myslitelné regiony (např. i Vietnam nebo Egypt):
Locale.setDefault(Locale.forLanguageTag("vi-VN"));
Locale.setDefault(Locale.forLanguageTag("ar-EG"));
Dosti řečí. Nejlepší učebnice programátora je komentovaný zdrojový kód. Uvedu tři příklady:
Příklad 1
Zadání jednoho datumu přes DatePicker (obrázek 1) a jeho konverze do řetězce prostřednictvím čtyř „formátovačů“ (třída DateTimeFormatter, viz obrázek 2). Klíčová je třída DatePicker. Ke zformátování použíjeme metodu format() – volá se přes instanci třídy LocalDate. Následující 2 obrázky zobrazují žádané chování programového kódu.
Obrázek 1: Zadání datumu prostřednictvím Kalendáře
Jednotlivé formáty se od sebe liší následovně. Praktická ukázka je na Obrázku 2
- Short: den, měsíc: každý 1-2 pozice, rok má 2 pozice
- Medium: den, měsíc: každý 1-2 pozice, rok má 4 pozice
- Long: navíc měsíc v písemném tvaru
- Full: navíc písemně vyjádřený dne týdne
Obrázek 2: Zobrazení vybraného datumu čtyřmi formátovači (short, medium, long, full)
Níže uvádím dvě klíčové sekvence z programového kódu. Celý zdrojový kód je ke stažení pod článkem.
1. Instance typu DatePicker a jeji inicializace aktuální datumem:
private DatePicker zadavacDatumu = null; zadavacDatumu = new DatePicker(LocalDate.now());
2. Formátování datumů:
/** přeformátování do String přes metodu format() */ String rtzFull, rtzLong, rtzMedium, rtzShort; LocalDate zadaneDatum = zadavacDatumu.getValue(); // sejmutí hodnoty datumu rtzFull = "FULL:"+zadaneDatum.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)); rtzLong = "LONG:"+zadaneDatum.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)); rtzMedium = "MEDIUM:"+zadaneDatum.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)); rtzShort = "SHORT:"+zadaneDatum.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT));
Příklad 2
Zadání časového období a vypsání jeho délky na obrazovce (viz Obrázek 3). Součástí zadání je i hlídání posloupnosti datumů. Jde o to aby nebyla zadána záporná délka trvání období. Jinými slovy: druhý datum musí mít hodnotu po prvním datumu (tedy vyšší). Inicializační délka období je týden (week, 7 dnů).
Obrázek 3: Úvodní obrazovka zadání délky období.
Uživatel vybírá Počátek období a Konec období. Nastavuje tím délku období. Aplikace hlídá, aby uživatel neměl možnost zvolit datumy, které by vytvořily “zápornou délku trvaní” období. Níže jsou uvedeny obrázky znázorňující zakázané datumy (jsou podbarveny růžově) při výběru počátečního a koncového datumu.
Obrázek 4. Vlevo: Zákaz datumů před 11.8.2015. Vpravo: Zákaz datumů po 18.8.2015.
Vyloučení některých datumů zajišťují instance dayCellFactoryKonec a dayCellFactoryZacatek, které využívají interface Callback. Klíčovými jsou metody:
setDisable(true) – "chrání" buňku datumu před zvolením od uživatele setStyle("-fx-background-color: #ffc0cb;") – nastavuje růžové podbarvení „disable“ buňky datumu
Metoda setDayCellFactory() propojuje Instance typu Callback (dayCellFactoryKonec, dayCellFactoryZacatek) s instancemi typu DatePicker (zadavacDatumuPocatek, zadavacDatumuKonec). Jejím vstupním parametrem je instance typu CallBack (dayCellFactoryKonec a dayCellFactoryZacatek).
Příklad 3
Tento příklad je nejjednodušší. Demonstruje, jak se dá v Kaledáři zapnout (vypnout) zobrazení čísla týdne v roce. Tuto vlastnost lze nastavit metodou setShowWeekNumbers(boolean). Metoda se volá přes instanci třídy DatePicker. V našem případě:
zadavacDatumu = new DatePicker(LocalDate.now()); zadavacDatumu.setShowWeekNumbers(false); // vypnutí zobrazování čísla týdne zadavacDatumu.setShowWeekNumbers(true); // zapnutí zobrazování čísla týdne
Kalendář při zapnutém zobrazování pak vypadá následovně (čísla týdnů jsou v prvním sloupci modře):
Obrázek 5: Kalendář se zapnutým zobrazováním čísla týdne
V článku jsem využil informace z dokumentace pro Java 8.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 127x (329.32 kB)
Aplikace je včetně zdrojových kódů v jazyce Java