java - make custom JTextField (JCurrencyField) -
i making jcurrencyfield use in program, finished creating i've faced issue.
jcurrencyfield normal jtextfield cannot accept character not number or decimal point .
, made specifications jcurrencyfield:
- the user cannot insert more 1 decimal point
.
. - the user cannot insert more 2 digits after decimal point.
the issue i've faced not being able insert digits before decimal point if there 2 digits after decimal point.
here code:
import javax.swing.*; import javax.swing.text.*; public class jcurrencyfield extends jtextfield { public jcurrencyfield() { ((abstractdocument)getdocument()).setdocumentfilter(new numberonlyfilter()); } private class numberonlyfilter extends documentfilter { public void insertstring(documentfilter.filterbypass fb, int offset, string text, attributeset attr) throws badlocationexception { if(!containsonlynumbers(text)) return; fb.insertstring(offset, text, attr); } public void replace(documentfilter.filterbypass fb, int offset, int length, string text, attributeset attr) throws badlocationexception { if(!containsonlynumbers(text)) return; fb.replace(offset, length, text, attr); } /** * method checks if string contains numbers */ public boolean containsonlynumbers(string str) { //it can't contain numbers if it's null or empty... if (str == null || str.length() == 0) return false; int counter = 0; for(int = 0; < gettext().length(); i++) { if(counter > 1) return false; if(gettext().charat(i) == '.') { counter++; } } int fp_counter = 0; int fp_index = -1; for(int = 0; < str.length(); i++) { if(counter >= 1) break; if(str.charat(i) == '.') { fp_counter++; fp_index = i; } } if(fp_counter > 1) return false; if(str.length() > fp_index + 3) return false; if(counter >= 1) { for(int = 0; < gettext().length(); i++) { if(gettext().charat(i) == '.') counter++; } } (int j = 0; j < str.length(); j++) { if(counter >= 1 && (str.charat(j) == '.')) return false; } int index = 0; boolean fp_flag = false; int sp_count = 0; for(int k = 0; k < gettext().length(); k++) { if(gettext().charat(k) == '.') { index = k; fp_flag = true; } if(fp_flag) sp_count++; if(sp_count > 2) return false; } //if(fp_flag && str.length() > 2) return false; if(fp_flag && index + 1 < gettext().length() && str.length() > 1) return false; //if(index + 2 < gettext().length() && fp_flag) return false; (int l = 0; l < str.length(); l++) { //if find non-digit character return false. if(str.charat(l) == '.') continue; if(!character.isdigit(str.charat(l))) return false; } return true; } } }
test program:
import java.awt.*; import java.util.*; import javax.swing.*; import javax.swing.border.*; public class test extends jframe { private jcurrencyfield txt = new jcurrencyfield(); public test() { super("test..."); setdefaultcloseoperation(exit_on_close); try{ uimanager.setlookandfeel(uimanager.getsystemlookandfeelclassname());} catch(exception e){ system.out.println("unable load windows , feel");} setpreferredsize(new dimension(300, 100)); ((jpanel) getcontentpane()).setborder(new emptyborder(13, 13, 13, 13) ); setlayout(new flowlayout()); txt.setpreferredsize(new dimension(100,30)); add(txt); pack(); setlocationrelativeto(null); setvisible(true); setresizable(false); } public static void main(string[] args) { new test(); } }
could please me solve issue?
you're testing wrong string in documentfilter.
you shouldn't testing text string rather string built text , document obtained filterbypass parameter since string want see if fulfills criteria. instance, not this:
public void insertstring(documentfilter.filterbypass fb, int offset, string text, attributeset attr) throws badlocationexception { if(!containsonlynumbers(text)) return; fb.insertstring(offset, text, attr); } public void replace(documentfilter.filterbypass fb, int offset, int length, string text, attributeset attr) throws badlocationexception { if(!containsonlynumbers(text)) return; fb.replace(offset, length, text, attr); }
but rather this:
private class numberonlyfilter extends documentfilter { public void insertstring(documentfilter.filterbypass fb, int offset, string text, attributeset attr) throws badlocationexception { stringbuilder sb = new stringbuilder(); sb.append(fb.getdocument().gettext(0, fb.getdocument().getlength())); sb.insert(offset, text); if (!containsonlynumbers(sb.tostring())) return; fb.insertstring(offset, text, attr); } public void replace(documentfilter.filterbypass fb, int offset, int length, string text, attributeset attr) throws badlocationexception { stringbuilder sb = new stringbuilder(); sb.append(fb.getdocument().gettext(0, fb.getdocument().getlength())); sb.replace(offset, offset + length, text); if (!containsonlynumbers(sb.tostring())) return; fb.replace(offset, length, text, attr); }
you need make changes containsonlynumbers method account these changes.
edit 1
, can done using toto's regex:
private boolean containsonlynumbers(string text) { pattern pattern = pattern.compile("\\d*(\\.\\d{0,2})?"); matcher matcher = pattern.matcher(text); boolean ismatch = matcher.matches(); return ismatch; }
Comments
Post a Comment