Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>By the time I wrote and tested the code below, you probably got lot of better answers...<br> I don't mind as I enjoyed the experiment/learning (still a bit green on the Swing front).</p> <p>[EDIT] Three years later, I am a bit less green, and I took in account the valid remarks of bobndrew. I have no problem with the key navigation that just works (perhaps it was a JVM version issue?). I improved the renderer to show highlight, though. And I use a better demo code. The accepted answer is probably better (more standard), mine is probably more flexible if you want a custom separator...</p> <p>The base idea is to use a renderer for the items of the combo box. For most items, it is a simple JLabel with the text of the item. For the last recent/most used item, I decorate the JLabel with a custom border drawing a line on its bottom.</p> <pre><code>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 &lt; 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; } } } </code></pre> <p>Separator class, can be thick, with custom color, etc.</p> <pre><code>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; } } </code></pre> <p>Test class:</p> <pre><code>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); } }); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload