如何在Java中为JComboBox添加分隔符?

我有一个JComboBox,并希望在元素列表中有一个分隔符。 我如何用Java做到这一点?

这个方便派对的示例场景是为字体系列选择制作combobox时; 类似于Word和Excel中的font-family-selection-control。 在这种情况下,我想在顶部显示最常用的字体,然后是分隔符,最后按字母顺序显示分隔符下面的所有字体系列。

任何人都可以帮助我如何做到这一点,或者这在Java中是不可能的?

有一个很简短的教程,其中有一个示例,展示了如何在java2上使用自定义ListCellRenderer http://www.java2s.com/Code/Java/Swing-Components/BlockComboBoxExample.htm

基本上它涉及在列表模型中插入已知占位符,当您在​​ListCellRenderer中检测到占位符时,您将返回“new JSeparator(JSeparator.HORIZONTAL)”的实例

当我编写并测试下面的代码时,你可能会得到很多更好的答案……
我不介意,因为我喜欢实验/学习(在Swing前面仍然有点绿色)。

[编辑]三年后,我有点不那么绿了,我考虑到了bobndrew的有效评论。 我对正常工作的密钥导航没有任何问题(可能是JVM版本问题?)。 不过,我改进了渲染器以显示高光。 我使用了更好的演示代码。 接受的答案可能更好(更标准),如果你想要一个自定义分隔符,我的可能更灵活…

基本思想是为combobox的项目使用渲染器。 对于大多数项目,它是一个带有项目文本的简单JLabel。 对于上一个最近/最常用的项目,我用自定义边框装饰JLabel,在其底部画一条线。

 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; } } } 

分隔类,可以厚,有自定义颜色等。

 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; } } 

测试类:

 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); } }); } } 

您可以使用自定义ListCellRenderer ,它将以不同方式绘制分隔符项。 查看文档和一个小教程 。