java - Strange tab-order with editable JComboBoxes -


i've got jframe looks this:

enter image description here

it's got 2 jtextfields on it, 1 jcombobox between them , jpanel @ bottom (that can't see).

one of features of jcombobox can given custom editor. these implement comboboxeditor interface. in each of following 3 cases, gui looks same, , have expected them behave same:

  • i not specify custom editor, , use default one.
  • i create custom editor editor component jtextfield.
  • i create custom editor editor component jpanel jtextfield on (using borderlayout).

when editor editable combo box set default, pressing tab moves focus top jtextfield editing area on jcombobox , other jtextfield. if create custom editor editor component jtextfield , otherwise expect, same thing happens.

but, if instead create custom editor editor component jpanel jtextfield added it, focus makes 1 additional stop. if focus on top jtextfield, pressing tab moves focus little arrow @ right of editable combo box before moving text area.

why happening? focus never moves on jpanel @ bottom of frame, why presence of jpanel holding jtextfield affect tab order on combo box?

the following s(-ish)scce, has 1 text field , 3 types of combo box on it:

import javax.swing.*; import java.awt.event.*; import java.awt.borderlayout; import java.awt.component; import java.awt.container; import java.awt.dimension;  public class comboboxtest extends jframe {   private jpanel layoutpanel;   private jtextfield meaninglesstextfield;   private jcombobox defaulteditorcombobox;   private jcombobox textfieldeditorcombobox;   private jcombobox paneleditorcombobox;    public comboboxtest()   {     setdefaultcloseoperation(windowconstants.exit_on_close);      layoutpanel = new jpanel();     layoutpanel.setlayout(new boxlayout(layoutpanel, boxlayout.y_axis));     meaninglesstextfield = new jtextfield();      defaulteditorcombobox = new jcombobox(); // default jcombobox.     defaulteditorcombobox.seteditable(true);      textfieldeditorcombobox = new jcombobox();     textfieldeditorcombobox.seteditable(true);     textfieldeditorcombobox.seteditor(new textfieldeditor());      paneleditorcombobox = new jcombobox();     paneleditorcombobox.seteditable(true);     paneleditorcombobox.seteditor(new paneleditor());      layoutpanel.add(box.createrigidarea(new dimension(500,0)));     layoutpanel.add(meaninglesstextfield);     layoutpanel.add(defaulteditorcombobox);     layoutpanel.add(textfieldeditorcombobox);     layoutpanel.add(paneleditorcombobox);      container contentpane = getcontentpane();     contentpane.add(layoutpanel, borderlayout.center);      pack();   }    public static void main(string[] args)   {     java.awt.eventqueue.invokelater(new runnable() {                     @override                     public void run()                     {                       new comboboxtest().setvisible(true);                     }     });   }    private class paneleditor extends jpanel implements comboboxeditor   {     public jtextfield inputtextfield = new jtextfield();      public paneleditor()     {       setlayout(new borderlayout());       add(inputtextfield, borderlayout.center);     }      @override     public string getitem()     {       return inputtextfield.gettext();     }      @override     public void setitem(object newtext)     {       if (newtext != null) {         inputtextfield.settext(newtext.tostring());       }       else {         inputtextfield.settext("");       }     }      @override     public component geteditorcomponent()     {       return this;     }      @override     public void removeactionlistener(actionlistener listener)     {       inputtextfield.removeactionlistener(listener);     }      @override     public void addactionlistener(actionlistener listener)     {       inputtextfield.addactionlistener(listener);     }      @override     public void selectall()     {       inputtextfield.selectall();     }   }    private class textfieldeditor extends paneleditor implements comboboxeditor   {     // same, except editor component jtextfield     // rather whole panel.     public textfieldeditor()     {     }      @override     public jtextfield geteditorcomponent()     {       return inputtextfield;     }   } }  

note: behaviour becomes problem if want add jlabel editor. have put jpanel there hold both label , text field.

the basic problem combo's ui delegate can't handle compound editor components. there several places assumes editor component target of whatever configuration needs do. concrete mis-behaviour here explicitly sets editor's focusability of combo itself

// in basiccomboboxui protected void configureeditor() {     ....     editor.setfocusable(combobox.isfocusable());     .... ] 

the implications

  • by default, panel's focusable true because combo's true
  • forcing panel's focusable false in constructor has no effect (the ui resets later on , whenever laf switched)
  • disabling combo's focusable disables panel's well

to fix on level of editor, can implement isfocusable return false unconditionally:

private class paneleditor extends jpanel implements comboboxeditor      public boolean isfocusable() {         return false;     }     ... } 

an aside: code hygiene, better not extend view implement role comboboxeditor (even though here need subclassed jpanel avoid problem, it's arguably borderline :-) - instead implement editor , let use tweaked panel.

also beware might stumble more problems compound editor (check code of basiccomboui more places assumes plain childless component), might consider not doing @ think of different way achieve requirement.


Comments

Popular posts from this blog

Unable to remove the www from url on https using .htaccess -