Swing’s JComboBox

The JComboBox in Java Swing can be used in two environments. The first is as normal component in a container and second as editor in a table, tree or list. In the first case every selection made in the list is propagated to the combo-box whereas in the second case it is only propagated when the popup is closed by pressing the enter key. Often the second behavior is better, especially when it comes to triggering a background task when the user finished the selection. There is already a bug in the Sun Bug database which discusses the correct behavior.

For uneditable combo-boxes it is easy to implement by simply overriding firePopupMenuCanceled(), firePopupMenuWillBecomeInvisible(), firePopupMenuWillBecomeInvisible() and fireActionPerformed(). Problems are starting when the combo-box is editable. In this case the editor didn’t update when the selection is finished. In the methods fire*Canceled() and fire*WillBecomeInvisibel() the property „JComboBox.isTableCellEditor“ is set to Boolean.FALSE, in fire*WillBecomeVisible() this property is set to Boolean.TRUE to activate/deactivate the behavior when the popup is shown/hidden before delegating to the super implementation. In fireActionPerformed() the popup needs to be hidden after before delegating to the super implementation.

Now in an editable combo box when the popup is going to be hidden the method actionPerformed(ActionEvent) is invoked. I finally found this by searching some hours through the code. To solve the update problem I need access to the popup. But the BasicComboBoxUI doesn’t provide any method therefore.

public void actionPerformed(ActionEvent evt) {
  ui = (BasicComboBoxUI) getUI();
  try {
    Field popupField = BasicComboBoxUI.class.getDeclaredField("popup");
    popupField.setAccessible(true);
    ComboPopup popup = (ComboPopup) popupField.get(ui);
    int selectedIndex = popup.getList().getSelectedIndex();
    setSelectedIndex(selectedIndex);
  } catch (NoSuchFieldException e) {
    e.printStackTrace();
  } catch (IllegalAccessException e) {
    e.printStackTrace();
  } finally {
    super.actionPerformed(evt);
  }
}

This snippet accesses the protected field, retrieves the selected index from the list in the popup and updates the combo box with the selected index which also updates the editor and model.

This hacky solution makes it possible to solve the problem but is completely against any OO principle. Going further one can inject different popups and customize the combo box but it is still against information hiding and encapsulation.

Isn’t there a better solution???

Schlagwörter: , , , ,

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: