Get the current selected item from the JComboBox popup (not selected item)

I would like to be able to respond when the current highlighted item in the JComboBox drop-down list changes. Note that I'm not looking for a way to get the currently selected item, but highlighted. When the mouse hovers over this popup, it selects the item at the mouse position, but it does not affect the currently selected item, so I can’t just listen through the ItemListener or ActionListener to achieve what I want.

I am trying to create a component that consists of a JComboBox and an associated tooltip that displays additional information (documentation) for the currently selected item.

As a first attempt, I add code to my constructor (extended JComboBox ):

 import java.awt.BorderLayout; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleState; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.SwingUtilities; import javax.swing.plaf.basic.ComboPopup; public class SomeFrame extends JFrame { private MyComboBox combo; public SomeFrame() { setDefaultCloseOperation(DISPOSE_ON_CLOSE); setSize(100,20); setLocationRelativeTo(null); setLayout(new BorderLayout()); combo = new MyComboBox(); combo.setModel(new DefaultComboBoxModel(new String[]{"one", "two", "three", "four"})); add(combo); pack(); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { SomeFrame frame = new SomeFrame(); frame.setVisible(true); } }); } // this is the important part private static class MyComboBox extends JComboBox { public MyComboBox() { getAccessibleContext().addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (AccessibleContext.ACCESSIBLE_STATE_PROPERTY.equals(evt.getPropertyName()) && AccessibleState.FOCUSED.equals(evt.getNewValue()) && getAccessibleContext().getAccessibleChild(0) instanceof ComboPopup) { ComboPopup popup = (ComboPopup) getAccessibleContext().getAccessibleChild(0); JList list = popup.getList(); System.out.println("--> " + String.valueOf(list.getSelectedValue())); } } }); } } } 

This seems to work, but I got into this code through several shadow channels and trial / error, so I think there should be a better way to do this. Any ideas? Is production even safe over code?

+4
source share
2 answers

A good question and a good solution - except that an error appears in accessCombo that does not update its internal wiring when updating the UI, i.e. when switching LAF:

  • available list selection changes are triggered by an internal ListSelectionListener registered in the comboPopup list
  • comboPopup is controlled by a ui delegate and recreated in installUI
  • accessCombo does not update its internal list for newly created and installed

Not much can be done about it. Therefore, I would listen directly to the list, then you have full control over re-posting with LAF changes:

 public static class XComboBox extends JComboBox { private ListSelectionListener listener; public XComboBox() { uninstall(); install(); } @Override public void updateUI() { uninstall(); super.updateUI(); install(); } private void uninstall() { if (listener == null) return; getPopupList().removeListSelectionListener(listener); listener = null; } protected void install() { listener = new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) return; JList list = getPopupList(); System.out.println("--> " + String.valueOf(list.getSelectedValue())); } }; getPopupList().addListSelectionListener(listener); } private JList getPopupList() { ComboPopup popup = (ComboPopup) getUI().getAccessibleChild(this, 0); return popup.getList(); } } 
+2
source

I am trying to create a component that consists of a JComboBox and related tooltip

Create your own renderer for the combo box. Then, in the renderer, use the setToolTipText (...) method.

The Note Tips tool for Cells from the JTable tutorial shows how to do this for tables. The concept should be the same for the comboBox renderer.

+3
source

All Articles