Let me start by saying this is an interesting question (+1 some time ago).
I had to quickly try to understand how difficult it is to achieve the desired result using JComboBox
. The conclusion I got (as @trashgod says in the comment above) was that this object was never designed to use other components, or at least for me it is.
Below is a sample that does what you want. You can use it as a start, but honestly, you should forget about using JComboBox
for this problem.
In no case, none of the examples below gives the correct way to solve the problem. It just shows the result of my attempts to approach the problem. The code below does not preserve good practice rules, for example. it mixes presentation with functionality (a visualization tool removes elements). It’s actually just hacking is not a real solution.
import java.awt.*; import java.awt.event.*; import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.*; public class ButtonCombo { private JPanel getContent() throws MalformedURLException { String[] ids = {"north", "west", "south", "east"}; JComboBox combo = new JComboBox(ids); Icon removeIcon = new ImageIcon(new URL("http://filesharefreak.org/images/red_x.png")); combo.setRenderer(new ButtonComboRenderer(removeIcon, combo)); JPanel panel = new JPanel(); panel.add(combo); return panel; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel = new JPanel(); panel.add(new ButtonCombo().getContent()); JButton button = new JButton("OKOKO"); panel.add(button); f.setContentPane(panel); f.setSize(300, 160); f.setLocation(200, 200); f.setVisible(true); } catch (MalformedURLException ex) { Logger.getLogger(ButtonCombo.class.getName()).log(Level.SEVERE, null, ex); } } }); } } class ButtonComboRenderer implements ListCellRenderer { Icon icon; JPanel panel; JLabel label; JButton button; public ButtonComboRenderer(Icon removeIcon, final JComboBox combo) { icon = removeIcon; label = new JLabel(); button = new JButton(icon); button.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); panel = new JPanel(new BorderLayout()); panel.add(label); panel.add(button, BorderLayout.EAST); panel.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { if (button.getX() < e.getX()) { System.out.println("button contains the click remove the item"); combo.removeItem(label.getText()); } } }); }
My final recommendation and the way I will do this: CREATE YOUR OWN COMPONENT. Make it extensible and mutable by separating it from the trigger and presentation, where both use the JComponent
, as they oppose using the renderer. This way you can capture and serve events on components, and not in this case all events are captured by the JList
used for rendering.
Below is a sample to help you get started. This is not a final solution, but it contains many important issues related to the creation of such a component. You should use the provided functions and wrap them all accordingly in one component:
import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import javax.swing.*; public class MockJComboBox { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { final JPanel popupContent = new JPanel(new GridLayout(0, 1)); popupContent.setBackground(Color.GREEN); popupContent.add(new JLabel("Content of popupContent panel")); popupContent.add(new JLabel("Content of popupContent panel")); popupContent.add(new JLabel("Content of popupContent panel")); popupContent.add(new JLabel("Content of popupContent panel")); popupContent.add(new JLabel("Content of popupContent panel")); popupContent.add(new JComboBox(new Object[]{"Content of popupContent panel"})); final JButton popupCloseButton = new JButton("X"); popupContent.add(popupCloseButton); final JScrollPane s = new JScrollPane(popupContent); s.setPreferredSize(new Dimension(popupContent.getPreferredSize().width + s.getVerticalScrollBar().getPreferredSize().width + s.getBorder().getBorderInsets(s).left + s.getBorder().getBorderInsets(s).right, 100)); JPanel panel = new JPanel(); panel.setPreferredSize(new Dimension(200, 200)); final JButton popupOpenButton = new JButton(); panel.add(popupOpenButton); final JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setContentPane(panel); final PopupFactory popupFactory = PopupFactory.getSharedInstance(); popupOpenButton.setAction(new AbstractAction("Open") { private Popup popup; private boolean isShown = false; @Override public void actionPerformed(ActionEvent e) { if (isShown) { popup.hide(); } else { popup = popupFactory.getPopup(popupOpenButton, s, popupOpenButton.getLocationOnScreen().x, popupOpenButton.getLocationOnScreen().y + popupOpenButton.getHeight()); popupCloseButton.setAction(new AbstractAction(popupCloseButton.getText()) { @Override public void actionPerformed(ActionEvent e) { isShown = false; popup.hide(); } }); popup.show(); } isShown = !isShown; } }); f.pack(); f.setVisible(true); } }); } }