Vorrei iniziare dicendo che questa è una domanda interessante (+1 qualche tempo fa).
Ho dovuto provare rapidamente e vedere di persona quanto sia difficile ottenere il risultato desiderato con JComboBox
. La conclusione che ho ottenuto (come dice @trashgod nel commento sopra) era che questo oggetto non è mai stato progettato per avere altri componenti o almeno mi sembra così.
Di seguito è un esempio che fa qualcosa che vuoi. Potresti usarlo come principio, ma per essere onesti dovresti dimenticarti di usare lo JComboBox
per questo problema.
Per nessun motivo il seguente esempio presenta il modo corretto di affrontare il problema. Mostra semplicemente il risultato dei miei tentativi di affrontare il problema. Il codice seguente non conserva le regole di buona pratica, ad es. mescola la presentazione con la funzionalità (il renderer rimuove gli elementi). Questo è in realtà solo un hack non una soluzione reale.
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());
}
}
});
}
//so we will install the mouse listener once
boolean isFirst = true;
@Override
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
if (isFirst) {
isFirst = false;
list.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
panel.dispatchEvent(e);
e.consume();
}
});
}
String text = (String) value;
label.setText(text);
if(text == null)
button.setIcon(null);
else if(button.getIcon() == null)
button.setIcon(icon);
panel.setBackground(isSelected ? Color.red : Color.white);
panel.setForeground(isSelected ? Color.white : Color.black);
return panel;
}
}
mia raccomandazione finale e il modo in cui lo farei è: costruire il vostro COMPONENTE PROPRIO. Rendilo estensibile e modificabile separandolo dal trigger e dalla presentazione, in cui entrambi utilizzano JComponent
mentre si oppongono all'uso di un renderer. In questo modo sarai in grado di acquisire e servire eventi sui componenti anziché come in questo caso tutti gli eventi vengono catturati dallo JList
utilizzato per il rendering.
Di seguito è un esempio che dovrebbe aiutare l'avvio. Non è la soluzione finale ma presenta molte importanti questioni relative alla realizzazione di tale componente. Si consiglia di utilizzare la funzionalità presentato e avvolgere il tutto di conseguenza in un unico componente:
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);
}
});
}
}
sono volete '1)' messo JLabel e con JButton a quella voce, '2)' per tutte le voci del JComboBox o no – mKorbel
@mKorbel Non sei sicuro di cosa intendi per il tuo primo punto? Ma per il secondo punto, sì. – berry120
vedo un problema importante, JComboBox drop_down si spegne dopo ogni Mouse_click all'elemento (Java1.4 e versioni successive), sei d'accordo e accettando che – mKorbel