java - How to request focus synchronously in Swing? -


when call component.requestfocusinwindow(), swing enqueues asynchronous focus_gained , focus_lost events rather synchronously transferring focus. workaround, appears defaultkeyboardfocusmanager trying simulate synchronously switching focus delaying dispatch of keyboard events until focus events have finished dispatching. appears isn’t working properly.

question: there way change focus synchronously in swing? defaultkeyboardfocusmanager trying simulate synchronous focus, , buggy? there focus manager correctly?

motivation: have jtextfield automatically transfers focus when it’s full. in writing integration tests using java.awt.robot, need behavior deterministic , not timing-dependent.

related question didn’t response: how grab focus now?

here’s demo. expected behavior: when hold down key, each jtextfield contain single character. actual behavior: focus not change fast enough multiple characters.

update: note behavior not specific progammatically changing focus. in third example, took out custom focus calls , instead set document update delay 500ms. typed 1tab2tab3tab4tab5tab6tab7tab8tab9tab0. can see, digits queued tab presses dropped.

screenshot screenshot after holding down 1 button enter image description here

import java.awt.*; import java.awt.event.*; import java.text.dateformat; import java.text.simpledateformat; import java.util.arraylist; import java.util.date; import java.util.logging.*;  import javax.swing.*; import javax.swing.grouplayout.group; import javax.swing.event.documentevent; import javax.swing.event.documentlistener;  public class awteventlistenerdemo {     public static final logger logger = logger.getlogger(awteventlistenerdemo.class.getname());     private static string keyeventtostring(keyevent keyevent) {         int id = keyevent.getid();         string eventname =             id == keyevent.key_pressed ? "key_pressed" :             id == keyevent.key_typed ? "key_typed" :             id == keyevent.key_released? "key_released" : "unknown " + id;         string = id == keyevent.key_typed ? "" + keyevent.getkeychar() : "#" + keyevent.getkeycode();         string componentstring = keyevent.getcomponent().getname();         if (componentstring == null) componentstring = keyevent.getcomponent().tostring();         return string.format("%12s %4s on %s", eventname, what, componentstring);     }     private static string focuseventtostring(focusevent focusevent) {         int id = focusevent.getid();         string eventname = id == focusevent.focus_gained ? "focus_gained" :             id == focusevent.focus_lost ? "focus_lost" :                 null;         if (eventname == null) return focusevent.tostring();         string componentstring = focusevent.getcomponent().getname();         if (componentstring == null) componentstring = focusevent.getcomponent().tostring();         return string.format("%12s on %s", eventname, componentstring);     }     private final awteventlistener logginglistener = new awteventlistener() {         @override public void eventdispatched(awtevent event) {             if (event instanceof keyevent) {                 keyevent keyevent = (keyevent) event;                 int id = keyevent.getid();                 if (id == keyevent.key_pressed && keyevent.getcomponent() instanceof jtextfield && ((jtextfield)keyevent.getcomponent()).getdocument().getlength() == 1) {                     eventqueue eventqueue = toolkit.getdefaulttoolkit().getsystemeventqueue();                     arraylist<awtevent> inqueue = new arraylist<awtevent>();                     int[] interestingids = new int[] {keyevent.key_pressed, keyevent.key_typed, keyevent.key_released, focusevent.focus_gained, focusevent.focus_lost};                     (int i: interestingids) {                         awtevent peek = eventqueue.peekevent(i);                         if (peek != null)                             inqueue.add(peek);                     }                     arraylist<string> inqueuestring = new arraylist<string>();                     (awtevent peek: inqueue) {                         if (peek instanceof keyevent) {                             inqueuestring.add(keyeventtostring((keyevent) peek));                         } else if (peek instanceof focusevent) {                             inqueuestring.add(focuseventtostring((focusevent) peek));                         }                     }                      logger.info(string.format("still in queue (in no particular order): %s", inqueuestring));                 }                 logger.info(keyeventtostring(keyevent));             } else {                 logger.info(event.tostring());             }         }     };     private jframe jframe;      public void init() {         long mask = awtevent.key_event_mask;  //  awtevent.mouse_event_mask |          toolkit.getdefaulttoolkit().addawteventlistener(logginglistener, mask);         if (jframe == null) jframe = new jframe(awteventlistenerdemo.class.getsimplename());         swingutilities.invokelater(new runnable() {             @override public void run() {                 initui();             }         });     }     public void cleanupforrestart() {         toolkit.getdefaulttoolkit().removeawteventlistener(logginglistener);     }     public void destroy() {         cleanupforrestart();         jframe.setvisible(false);         jframe = null;     }      public void initui() {         grouplayout grouplayout = new grouplayout(jframe.getcontentpane());         jframe.getcontentpane().removeall();         jframe.getcontentpane().setlayout(grouplayout);          jbutton jbutton = new jbutton(new abstractaction("restart") {             private static final long serialversionuid = 1l;             @override public void actionperformed(actionevent e) {                 cleanupforrestart();                 init();             }         });         grouplayout.setautocreategaps(true);         grouplayout.setautocreatecontainergaps(true);         group verticalgroup = grouplayout.createsequentialgroup()                 .addcomponent(jbutton);         group horizontalgroup = grouplayout.createparallelgroup()                 .addcomponent(jbutton);         grouplayout.setverticalgroup(verticalgroup);         grouplayout.sethorizontalgroup(horizontalgroup);         (int = 0; < 10; i++) {             final jtextfield jtextfield = new jtextfield();             jtextfield.setname(string.format("jtextfield %d", i));             verticalgroup.addcomponent(jtextfield);             horizontalgroup.addcomponent(jtextfield);             boolean usedocumentlistener = true;             final boolean usefocusrootancestor = false;             if (usedocumentlistener) {                 documentlistener listener = new documentlistener() {                     @override public void removeupdate(documentevent e) { }                     @override public void insertupdate(documentevent e) {                          // simulate slow event listener. when listener                         // slow, problems worse.                         try {                             thread.sleep(50);                         } catch (interruptedexception e1) {                             logger.warning(e1.tostring());                         }                         if (e.getdocument().getlength() > 0) {                             // these 2 methods of transferring focus appear                             // equivalent.                             if (usefocusrootancestor) {                                 container focusroot = jtextfield.getfocuscyclerootancestor();                                 focustraversalpolicy policy = focusroot.getfocustraversalpolicy();                                 component nextcomponent = policy.getcomponentafter(focusroot, jtextfield);                                 nextcomponent.requestfocusinwindow();                             } else {                                 keyboardfocusmanager.getcurrentkeyboardfocusmanager().focusnextcomponent(jtextfield);                             }                         }                     }                     @override public void changedupdate(documentevent e) { }                 };                 jtextfield.getdocument().adddocumentlistener(listener);             }         }          if (!jframe.isvisible()) {             jframe.pack();             jframe.setdefaultcloseoperation(windowconstants.dispose_on_close);             jframe.setvisible(true);         }     }     public static void main(string[] argv) {         // use single-line console log handler.         logmanager.getlogmanager().reset();         formatter formatter = new formatter() {             private simpledateformat dateformat = new simpledateformat("kk:mm:ss.sss");             @override             public string format(logrecord logrecord) {                 date date = new date(logrecord.getmillis());                 dateformat.gettimeinstance().format(date);                 return string.format("%s %s %s %s%n",                         dateformat.format(date),                         logrecord.getloggername(),                         logrecord.getlevel(),                         logrecord.getmessage());             }         };         consolehandler consolehandler = new consolehandler();         consolehandler.setformatter(formatter);         consolehandler.setlevel(level.finest);         logger.addhandler(consolehandler);         logger focuslogger = logger.getlogger("java.awt.focus.defaultkeyboardfocusmanager");         focuslogger.setlevel(level.finest);         focuslogger.addhandler(consolehandler);           final awteventlistenerdemo demo = new awteventlistenerdemo();         demo.init();     } } 

yes, focus pretty asynchronous, should wrapped int invokelater, no way

edit

and nice workaround @camickr

import javax.swing.*; import java.awt.*; import java.awt.event.*; //http://www.coderanch.com/t/342205/gui/java/tab-order-swing-components public class testing {      private static final long serialversionuid = 1l;     private component[] focuslist;     private int focusnumber = 0;     private jframe frame;      public testing() {         jtextfield tf1 = new jtextfield(5);         jtextfield tf2 = new jtextfield(5);         jtextfield tf3 = new jtextfield(5);         jbutton b1 = new jbutton("b1");         jbutton b2 = new jbutton("b2");         tf2.setenabled(false);         focuslist = new component[]{tf1, b1, tf2, b2, tf3};         jpanel panel = new jpanel(new gridlayout(5, 1));         panel.add(tf1);         panel.add(b1);         panel.add(tf2);         panel.add(b2);         panel.add(tf3);         frame = new jframe();         frame.setfocustraversalpolicy(new myfocustraversalpolicy());         frame.add(panel);         frame.pack();         frame.setlocation(150, 100);         frame.setdefaultcloseoperation(jframe.exit_on_close);         frame.setvisible(true);         keyboardfocusmanager.getcurrentkeyboardfocusmanager().addkeyeventdispatcher(new keyeventdispatcher() {              public boolean dispatchkeyevent(keyevent ke) {                 if (ke.getid() == keyevent.key_pressed) {                     if (ke.getkeycode() == keyevent.vk_tab) {                         component comp = keyboardfocusmanager.getcurrentkeyboardfocusmanager().getfocusowner();                         if (comp.isenabled() == false) {                             if (ke.isshiftdown()) {                                 keyboardfocusmanager.getcurrentkeyboardfocusmanager().focuspreviouscomponent();                             } else {                                 keyboardfocusmanager.getcurrentkeyboardfocusmanager().focusnextcomponent();                             }                         }                     }                 }                 return false;             }         });     }      private class myfocustraversalpolicy extends focustraversalpolicy {          public component getcomponentafter(container focuscycleroot, component acomponent) {             focusnumber = (focusnumber + 1) % focuslist.length;             return focuslist[focusnumber];         }          public component getcomponentbefore(container focuscycleroot, component acomponent) {             focusnumber = (focuslist.length + focusnumber - 1) % focuslist.length;             return focuslist[focusnumber];         }          public component getdefaultcomponent(container focuscycleroot) {             return focuslist[0];         }          public component getlastcomponent(container focuscycleroot) {             return focuslist[focuslist.length - 1];         }          public component getfirstcomponent(container focuscycleroot) {             return focuslist[0];         }     }      public static void main(string[] args) {         swingutilities.invokelater(new runnable() {              @override             public void run() {                 testing testing = new testing();             }         });     } } 

Comments

Popular posts from this blog

c# - SVN Error : "svnadmin: E205000: Too many arguments" -

c# - Copy ObservableCollection to another ObservableCollection -

All overlapping substrings matching a java regex -