如何在Java中将分隔符添加到JComboBox?
我有一个JComboBox,想在元素列表中有一个分隔符。如何在Java中执行此操作?
一个方便使用的示例场景是制作用于字体族选择的组合框。与Word和Excel中的font-family-selection-control类似。在这种情况下,我想在顶部显示最常用的字体,然后显示一个分隔符,最后按字母顺序显示分隔符下方的所有字体系列。
谁能帮我解决这个问题,或者在Java中是不可能的吗?
解决方案
我们可以使用自定义的" ListCellRenderer",它将以不同的方式绘制分隔符项目。请参阅文档和一个小教程。
有一个简短的教程,其中包含一个示例,该示例显示了如何在java2s上使用自定义ListCellRenderer
http://www.java2s.com/Code/Java/Swing-Components/BlockComboBoxExample.htm
基本上,这涉及在列表模型中插入一个已知的占位符,并且当我们在ListCellRenderer中检测到占位符时,将返回" new JSeparator(JSeparator.HORIZONTAL)"的实例。
在我编写和测试下面的代码时,我们可能已经得到了很多更好的答案...
我喜欢实验/学习(我在Swing前面还是有点绿色),所以我不介意。
[编辑]三年后,我的环保意识有所下降,我考虑了bobndrew的有效言论。我对可以正常使用的键导航没有任何问题(也许这是JVM版本问题?)。不过,我改进了渲染器以使其突出显示。而且我使用了更好的演示代码。可接受的答案可能更好(更标准),如果我们想要自定义分隔符,我的可能会更灵活...
基本思想是为组合框的项目使用渲染器。对于大多数项目,它是带有项目文本的简单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); } }); } }