als ich schrieb und den Code unten getestet, haben Sie sich wahrscheinlich viel bessere Antworten ...
ich nichts dagegen haben, wie ich das Experiment genossen/Lernen (immer noch ein bisschen grün auf der Swing-Front).
[Bearbeiten] Drei Jahre später bin ich ein bisschen weniger grün, und ich habe die gültigen Bemerkungen von bobndrew berücksichtigt. Ich habe kein Problem mit der Schlüsselnavigation, die gerade funktioniert (vielleicht war es ein JVM Versions-Problem?). Ich habe den Renderer verbessert, um highlight anzuzeigen, obwohl. Und ich benutze einen besseren Demo-Code. Die angenommene Antwort ist wahrscheinlich besser (mehr Standard), meins ist wahrscheinlich flexibler, wenn Sie ein benutzerdefiniertes Trennzeichen wünschen ...
Die Grundidee besteht darin, einen Renderer für die Elemente des Kombinationsfelds zu verwenden. Für die meisten Artikel ist es ein einfaches JLabel mit dem Text des Artikels. Für das zuletzt verwendete/am häufigsten verwendete Element dekoriere ich das JLabel mit einem benutzerdefinierten Rahmen, der eine Linie auf seiner Unterseite zeichnet.
import java.awt.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class TwoPartsComboBox extends JComboBox
{
private int m_lastFirstPartIndex;
public TwoPartsComboBox(String[] itemsFirstPart, String[] itemsSecondPart)
{
super(itemsFirstPart);
m_lastFirstPartIndex = itemsFirstPart.length - 1;
for (int i = 0; i < itemsSecondPart.length; i++)
{
insertItemAt(itemsSecondPart[i], i);
}
setRenderer(new JLRenderer());
}
protected class JLRenderer extends JLabel implements ListCellRenderer
{
private JLabel m_lastFirstPart;
public JLRenderer()
{
m_lastFirstPart = new JLabel();
m_lastFirstPart.setBorder(new BottomLineBorder());
// m_lastFirstPart.setBorder(new BottomLineBorder(10, Color.BLUE));
}
@Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
if (value == null)
{
value = "Select an option";
}
JLabel label = this;
if (index == m_lastFirstPartIndex)
{
label = m_lastFirstPart;
}
label.setText(value.toString());
label.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
label.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
label.setOpaque(true);
return label;
}
}
}
Separator Klasse kann dick sein, mit benutzerdefinierter Farbe usw.
import java.awt.*;
import javax.swing.border.AbstractBorder;
/**
* Draws a line at the bottom only.
* Useful for making a separator in combo box, for example.
*/
@SuppressWarnings("serial")
class BottomLineBorder extends AbstractBorder
{
private int m_thickness;
private Color m_color;
BottomLineBorder()
{
this(1, Color.BLACK);
}
BottomLineBorder(Color color)
{
this(1, color);
}
BottomLineBorder(int thickness, Color color)
{
m_thickness = thickness;
m_color = color;
}
@Override
public void paintBorder(Component c, Graphics g,
int x, int y, int width, int height)
{
Graphics copy = g.create();
if (copy != null)
{
try
{
copy.translate(x, y);
copy.setColor(m_color);
copy.fillRect(0, height - m_thickness, width - 1, height - 1);
}
finally
{
copy.dispose();
}
}
}
@Override
public boolean isBorderOpaque()
{
return true;
}
@Override
public Insets getBorderInsets(Component c)
{
return new Insets(0, 0, m_thickness, 0);
}
@Override
public Insets getBorderInsets(Component c, Insets i)
{
i.left = i.top = i.right = 0;
i.bottom = m_thickness;
return i;
}
}
Prüfklasse:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class TwoPartsComboBoxDemo extends JFrame
{
private TwoPartsComboBox m_combo;
public TwoPartsComboBoxDemo()
{
Container cont = getContentPane();
cont.setLayout(new FlowLayout());
cont.add(new JLabel("Data: ")) ;
String[] itemsRecent = new String[] { "ichi", "ni", "san" };
String[] itemsOther = new String[] { "one", "two", "three" };
m_combo = new TwoPartsComboBox(itemsRecent, itemsOther);
m_combo.setSelectedIndex(-1);
cont.add(m_combo);
m_combo.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
String si = (String) m_combo.getSelectedItem();
System.out.println(si == null ? "No item selected" : si.toString());
}
});
// Reference, to check we have similar behavior to standard combo
JComboBox combo = new JComboBox(itemsRecent);
cont.add(combo);
}
/**
* Start the demo.
*
* @param args the command line arguments
*/
public static void main(String[] args)
{
// turn bold fonts off in metal
UIManager.put("swing.boldMetal", Boolean.FALSE);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame demoFrame = new TwoPartsComboBoxDemo();
demoFrame.setTitle("Test GUI");
demoFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demoFrame.setSize(400, 100);
demoFrame.setVisible(true);
}
});
}
}
Das 'BlockComboBoxExample' Beispiel brechen die Cursor-Taste und die erst- Briefschlüssel Navigation. Santhosh Kumars [Beispiel] (http://www.jroller.com/santhosh/entry/jcombobox%5Fitems%5Fwith%5Fseparators) scheint besser zu funktionieren. – bobndrew