Question

J'ai une JComboBox et j'aimerais avoir un séparateur dans la liste des éléments. Comment faire cela en Java?

Un exemple de scénario dans lequel cela serait utile consiste à créer une liste déroulante pour la sélection famille de polices; semblable au contrôle font-family-selection-control de Word et Excel. Dans ce cas, j'aimerais afficher les polices les plus utilisées en haut, puis un séparateur et enfin toutes les familles de polices situées en dessous du séparateur, dans l'ordre alphabétique.

Quelqu'un peut-il m'aider à faire cela ou est-ce impossible en Java?

Était-ce utile?

La solution

Il y a un tutoriel assez court avec un exemple qui montre comment utiliser un ListCellRenderer personnalisé sur java2s   http://www.java2s.com/Code/Java/Swing-Components /BlockComboBoxExample.htm

En gros, cela implique d'insérer un espace réservé connu dans votre modèle de liste et, lorsque vous le détectez dans ListCellRenderer, vous renvoyez une instance de "new JSeparator (JSeparator.HORIZONTAL)"

Autres conseils

Au moment où j'ai écrit et testé le code ci-dessous, vous avez probablement obtenu de nombreuses meilleures réponses ...
Cela ne me dérange pas car j'ai apprécié l'expérience / l'apprentissage (toujours un peu vert sur le front du Swing).

[EDIT] Trois ans plus tard, je suis un peu moins vert et j'ai pris en compte les remarques valables de Bobndrew. Je n’ai aucun problème avec la navigation par clé qui fonctionne (c’est peut-être un problème de version de JVM?). J'ai cependant amélioré le rendu pour afficher les points forts. Et j'utilise un meilleur code de démonstration. La réponse acceptée est probablement meilleure (plus standard), la mienne est probablement plus flexible si vous voulez un séparateur personnalisé ...

L’idée de base est d’utiliser un moteur de rendu pour les éléments de la liste déroulante. Pour la plupart des éléments, il s’agit d’un simple JLabel avec le texte de l’article. Pour le dernier élément récent / le plus utilisé, je décore le JLabel avec une bordure personnalisée en traçant une ligne sur son bas.

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

La classe de séparation peut être épaisse, avec une couleur personnalisée, etc.

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

Classe de test:

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

Vous pouvez utiliser un ListCellRenderer personnalisé pour dessiner les éléments de séparation différemment. Voir docs et un petit tutoriel .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top