Java: JFormatedTextField pomocí MaskFormatter
A aplikacích psaných v javě často potřebujeme vytvářet textové pole, které bude obsahovat přesný formát řetězce. Pomocí MaskFormatter můžeme snadno vytvořit masku pro takový řetězec a implementovat ji do JFormatedTextField.
Možná jste již narazily na problém, kdy potřebujete daný JTextFieldu vytvořit tak, aby do něj šel zapsat pouze určitý formát textu. Mám na mysli striktně dané formáty jako jsou například telefonní čísla, PSČ, rodné čísla, nebo libovolný vámi vytvořený formát řetězce.
Takový problém lze řešit například přidáním FocusListeneru a kontrolou ve focusLost(FocusEvent i), ovšem tímto způsobem kontrolujete řetězec až po jeho napsání a uživateli je umožněno v průběhu psaní dělat nesmyslné překlepy.
Takováto základní pravidla pro řetězce umožňuje vytvářet java pomocí MaskFormatteru, ve kterém můžete přímo pro každé místo v řetězci určit o jaký se může jednat znak a který znak bude na daném místě povolený.
Nejprve se podívejte na tabulku, ve které je určeno kterými znaky můžete zastupovat pravidla ve vašem řetězci a vytvářet tak masky:
Znak | Význam | Povoleno |
---|---|---|
# | Libovolné číslo. | 0-9 |
U | Libovolný znak. Po napsání bude převeden na velké písmeno | a-z, A-Z |
L | Libovolný znak. Po napsání bude převeden na malé písmeno | a-z, A-Z |
A | Libovolný znak abecedy nebo číslo. | 0-9, a-z, A-Z |
? | Libovolné písmeno. | a-z, A-Z |
* | Libovolný znak | Cokoli |
H | Hexadecimární čísla | 0-9, a-f, A-F |
Pomocí těchto speciálních znaků můžeme vytvářet masky, do kterých bude uživatel nucen psát pouze námi dané znaky.
Jednoduchá maska například pro rodné číslo by mohla vypadat následovně:
1 2 |
MaskFormatter pn_formatter = new MaskFormatter("###### / ####"); JFormattedTextField personal_number = new JFormattedTextField(pn_formatter); |
Nejprve si vytvoříme MaskFormatter, a ten přidáme do JFormattedTextFieldu. Takto vytvořený JFormattedTextField bude na první pohled vypadat podobně jako klasický JTextField, jenom s tím rozdílem, že do něj nebude možné psát písmena, ale pouze čísla.
Navíc bude obsahovat lomítko, které jsme do masky přidali. Po napsání prvních 6 číslic se kurzor automaticky přesune za lomítko a zde bude psaní pokračovat dalšími 4 číslicemi.
Pomocí speciálních znaků tak můžete přehledně vytvořit libovolnou masku a uživatele donutit dodržovat přesný formát.
Ještě uvedu dve užitečné funkce, které se vám budou hodit při úpravě formátu textového pole a pro upřesnění masky:
SetPlaceholderCharacter
Funkce SetPlaceholderCharacter určuje, kterým znakem budou vyplněna volné místa namísto znaků po načtení formuláře.
Pomocí této funkce můžeme například určit, aby nevyplněné pole obsahovalo namísto prázdných mezer podtržítka. Použití je velmi jednoduché:
1 |
pn_formatter.setPlaceholderCharacter('_'); |
setValidCharacters
Pomocí setValidCharacters můžeme přímo určit, které znaky budou povolené. Takže kdybychom například věděli že v zadávaném rodném čísle, pro které jsme si připravili masku se nebude vyskytovat nula, a tím pádem bychom nechtěli aby ji bylo možné zadat, mohli bychom masku upravit takovýmto způsobem:
1 |
pn_formatter.setValidCharacters("123456789"); |
Tím určíme, že bude možné zadat pouze čísla od 1 do 9 a nikoli 0.
Závěrem
Použití MaskFormatteru je jednoduché a výsledná efekt je velmi pozitivní. Jeho použitím si můžete ušetřit základní kontroly formulářových textových polí a uživatele vyvarujete zbytečných překlepů a následných oprav.
Závěrem ještě uvedu ukázkový zdrojový kód, ve kterém jsou připraveny dvě masky a implementovány do dvou JFormattedTextFieldu včetně nastavení velikosti textového pole:
1 2 3 4 5 6 7 8 9 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.text.ParseException; import javax.swing.BorderFactory; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.text.MaskFormatter; public class textformatter extends JFrame { //globalni promenne MaskFormatter pn_formatter; MaskFormatter phone_formatter; //konstruktor public textformatter(){ //nastaveni rozmeru okna setSize(new Dimension(200, 130)); //titulek okna setTitle("MaskFormatter"); //defaultni operace pri zavreni setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //znemozneni zmeny rozmeru okna setResizable(false); //vytvoreni layoutu pro container FlowLayout fl = new FlowLayout(); Container cont = getContentPane(); cont.setLayout(fl); //vytvoreni MaskFormatteru pro rodne cislo try { pn_formatter = new MaskFormatter("###### / ####"); //nastaveni vychozich prazdnych znaku pn_formatter.setPlaceholderCharacter('_'); //nastaveni povolenych znaku pn_formatter.setValidCharacters("123456789"); } catch (ParseException e) { e.printStackTrace(); } //vytvoreni JFormattedTextFieldu a navazani na MaskFormatter JFormattedTextField personal_number = new JFormattedTextField(pn_formatter); //nastaveni ramecku personal_number.setBorder(BorderFactory.createTitledBorder("Rodné číslo:")); //nastaveni rozmeru textoveho pole personal_number.setPreferredSize( new Dimension( 160, 43 ) ); //vytvoreni maskformatteru pro telefon try { phone_formatter = new MaskFormatter("( +420 ) ### - ### - ###"); //nastaveni prazdkych vychozich znaku phone_formatter.setPlaceholderCharacter('?'); } catch (ParseException e) { e.printStackTrace(); } //vytvoreni noveho JFormattedTextFieldu a navazani na MaskFormatter JFormattedTextField phone = new JFormattedTextField(phone_formatter); //nastaveni ramecku phone.setBorder(BorderFactory.createTitledBorder("Telefon:")); //nastaveni rozmeru phone.setPreferredSize( new Dimension( 160, 43 ) ); cont.add(personal_number ); cont.add(phone); setVisible(true); } public static void main(String[] args) { new textformatter(); } } |