java - InputVerifier incorrectly yielding focus and need advice using it with other ActionListener methods -
i have gui in user enters measurements number of fields , calculates result based on measurement. trying implement next fields-
the values entered must in proper range i have alternative dialog among other things, sets units. field has value in it, must updated current units when value in field changes, need see if measurements entered, , if so, (or redo) calculation.i've done tables (the model retained values in 'standard' units , custom renderer , cell editor handled showing user values in current units , storing values in 'standard' units in model).
i don't believe jtextfield has renderer override, document editor looked bit daunting, , user didn't jformattedtextfield, thought create custom jtextfield stored 'standard' value , utilize inputverifier used table.
example code below (it works). used jcombobox stand-in alternative dialog , implemented 1 text field.
i utilize expert advice-
i may misunderstanding setinputverifier. thought should invoked if attempted alter focus text field , maintain focus in text field if said don't yield focus. if set 'aa' in text field (without hitting enter) can alter value in combobox. debugging println say-volume value changed (f) // focus listener fired off updating model // focus listener verifying: 'aa' // input verifier invalid number // input verifier
the text box gets reddish outline , hear beep, combobox active. text field ends empty value, since combobox action listener called when alter value. why allowed alter combox value? how stop that?
my adding inputverifier, 2 actionlisteners , focuslistener seems wrong. logical separation of tasks. should doing? should extend doubleverifier , override actionperformed include what's in doubleverifier , in volumevaluelistener?i want text field validated , view of underlying info updated either when user enters (cr) , stays in field or when leaves field. why action , focus listeners.
any corrections or insights welcome.
unitstextfield.java
import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; class unitstextfield extends jtextfield { double modelvalue = null; double viewvalue = null; unitstextfield( int cols ) { super( cols ); } public void updatemodel() throws exception { system.out.println( "updating model" ); modelvalue = conversion.modelvalue( this.gettext() ); } public void refreshview() { this.settext( conversion.viewstring( modelvalue ) ); } public double getmodelvalue() { homecoming modelvalue; } }
unitslabel.java
import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; class unitslabel extends jlabel { public void refreshview() { super.settext( conversion.viewlabel() ); } }
conversion.java
import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; class conversion { public static enum units {cc, l, gal}; public static map<string,units> unittypes = new hashmap<string, units>() { { put( "cubic centimeters", units.cc ); put( "liters", units.l ); put( "gallons", units.gal ); } }; public static map<units,double> unitconversions = new hashmap<units, double>() { { put( units.cc, 1.0 ); put( units.l, 1000.0 ); put( units.gal, 4404.9 ); } }; private static units unittype = units.cc; public static void setunittype( units unit ) { unittype = unit; } public static void setunittype( string unitstring ) { unittype = unittypes.get(unitstring); } public static string[] getunitnames() { homecoming (unittypes.keyset()).toarray(new string[0]); } public static string viewlabel() { homecoming unittype.tostring(); } public static double modelvalue( string viewstring ) throws exception { double value = null; if (viewstring != null && viewstring.length() > 0) { value = double.parsedouble( viewstring ); value = value * unitconversions.get(unittype); } homecoming value; } public static string viewstring( double modelvalue ) { double value = null; if (modelvalue != null) { value = modelvalue / unitconversions.get(unittype); } homecoming (value == null) ? "" : value.tostring(); } }
doubleverifier.java
import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; import java.text.numberformat; import java.awt.toolkit; public class doubleverifier extends inputverifier implements actionlistener { public boolean shouldyieldfocus(jcomponent input) { jtextfield tf = (jtextfield) input; boolean inputok = verify(input); if (inputok) { tf.setborder( new lineborder( color.black ) ); homecoming true; } else { tf.setborder( new lineborder( color.red ) ); toolkit.getdefaulttoolkit().beep(); homecoming false; } } public boolean verify(jcomponent input) { jtextfield tf = (jtextfield) input; string txt = tf.gettext(); double n; system.out.println( "verifying: '" + txt + "'" ); if (txt.length() != 0) { seek { n = double.parsedouble(txt); } grab (numberformatexception nf) { system.out.println( "invalid number" ); homecoming false; } } homecoming true; } public void actionperformed(actionevent e) { system.out.println( "input verification" ); jtextfield source = (jtextfield) e.getsource(); shouldyieldfocus(source); } }
volumetextfieldtest.java
import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; class volumetextfieldtest extends jframe { private jcombobox volumecombo; private unitslabel volumelabel; private unitstextfield volumefield; public volumetextfieldtest() { setsize(300, 100); setdefaultcloseoperation(jframe.exit_on_close); volumecombo = new jcombobox( conversion.getunitnames() ); volumecombo.addactionlistener( new volumelistener() ); volumecombo.addfocuslistener( new volumelistener() ); volumelabel = new unitslabel(); volumelabel.refreshview(); volumefield = new unitstextfield(8); doubleverifier dverify = new doubleverifier(); volumefield.setinputverifier( dverify ); volumefield.addactionlistener( dverify ); volumefield.addactionlistener( new volumevaluelistener() ); volumefield.addfocuslistener( new volumevaluelistener() ); jpanel mypane = new jpanel(); mypane.add(volumecombo); mypane.add(volumefield); mypane.add(volumelabel); getcontentpane().add(mypane); setvisible(true); } public class volumelistener implements actionlistener, focuslistener { @override public void actionperformed( actionevent ae ) { system.out.println( "volume type changed" ); conversion.setunittype( (string) volumecombo.getselecteditem() ); volumelabel.refreshview(); volumefield.refreshview(); } @override public void focusgained( focusevent fg ) { } @override public void focuslost( focusevent fl ) { system.out.println( "volume type changed" ); conversion.setunittype( (string) volumecombo.getselecteditem() ); volumelabel.refreshview(); volumefield.refreshview(); } } public class volumevaluelistener implements actionlistener, focuslistener { @override public void actionperformed( actionevent ae ) { system.out.println( "volume value changed (a)" ); seek { volumefield.updatemodel(); volumefield.refreshview(); } grab (exception e) {} } @override public void focusgained( focusevent fg ) { } @override public void focuslost( focusevent fl ) { system.out.println( "volume value changed (f)" ); seek { volumefield.updatemodel(); volumefield.refreshview(); } grab (exception e) {} } } public static void main(string[] args) { seek { swingutilities.invokelater( new runnable() { public void run () { volumetextfieldtest runme = new volumetextfieldtest(); } }); } grab (exception e) { system.out.println( "gui did not start" ); } } }
i understand part of problem additional research. inputverifier concerned focus. if input invalid, not transfer focus, however, allow action events occur. complaints have seen have been related people had exit button action performed if info in field invalid. in case, have combobox action can still performed though inputverifier complaining invalid info (text field gets reddish border , beeps). in respect aspect of problem, don't believe there solution. 1 suggestion variable action listeners checked before performing action, set inputverifier. i've got (ideally) reusable routines in separate files, have problems solution.
i'm still unsure of how gracefully handle situation have several distinct generic actions (verify input, convert units, update view) needed given field , want assign actionlisteners , focuslisteners in sequential order. thought right have base of operations listener, illustration verifies input, extend , override actionperformed, focusgained , focuslost methods, though seems end duplicating code every combination.
java actionlistener inputverifier
No comments:
Post a Comment