2008-09-26 5 views
10

Ich habe eine JComboBox und möchte ein Trennzeichen in der Liste der Elemente haben. Wie mache ich das in Java?Wie füge ich ein Trennzeichen zu einer JComboBox in Java hinzu?

Ein Beispielszenario, in dem dies nützlich wäre, ist die Erstellung einer Combobox für die Schriftfamilienauswahl; ähnlich wie die Schriftfamilie-Auswahlsteuerung in Word und Excel. In diesem Fall möchte ich die am häufigsten verwendeten Schriftarten oben, dann ein Trennzeichen und schließlich alle Schriftfamilien unterhalb des Trennzeichens in alphabetischer Reihenfolge zeigen.

Kann mir jemand dabei helfen oder ist das in Java nicht möglich?

Antwort

7

Es ist ein ziemlich kurzes Tutorial mit einem Beispiel, das zeigt, wie eine benutzerdefinierte ListCellRenderer auf java2s verwenden http://www.java2s.com/Code/Java/Swing-Components/BlockComboBoxExample.htm

Grundsätzlich geht es um eine bekannte Platzhalter in der Liste Modell einfügen und wenn Sie den Platzhalter in den ListCellRenderer erkennen Sie geben eine Instanz von ‚neuen JSeparator (JSeparator.HORIZONTAL)‘

+2

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

2

Sie können eine benutzerdefinierte ListCellRenderer verwenden, die die Trennelemente anders zeichnen würde. Siehe docs und eine kleine tutorial.

4

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

Deine Variablenbenennung ist hier nicht das Schlechteste: Du durchbrichst die gesamte Combobox-Item-Auswahl: Die Auswahl ist nicht mehr gemalt und die First-Letter-Key-Jumps sind kaputt. Und Sie sollten 'm_combo' und' m_renderer' im kleinstmöglichen Umfang definieren (in 'public TestGui()'). Und sollte keinen glooooobal 'm_lastRecentIndex' für den Renderer ** und ** die 'TestGui'-Klasse verwenden (was eine einsame Hauptklasse und keine' JFrame'-Unterklasse sein sollte). Aber ich mag den Hosenträger-Stil! – bobndrew

+0

@bobndrew: hey! Wie ich schrieb, war ich zu der Zeit ein Neuling (3 Jahre schon!). Unter den Sünden, auf die Sie nicht hinweisen, habe ich wahrscheinlich eine Swing-Testvorlage verwendet, die ich gefunden habe, und schlimmer noch, ich habe SwingUtilities.invokeLater nicht verwendet! Der Code, den ich derzeit benutze, ist zumindest (aber es ist immer noch eine JFrame-Unterklasse ...). Und m_lastRecentIndex ist mehr lokal ... Aber die meisten Ihrer Kritik ist über eine schnell gemacht Test-Klasse, die nicht wirklich Produktionscode ist.Heute schenke ich solchen Code mehr Aufmerksamkeit, da Neulinge sich davon inspirieren lassen können ... :-) Außerdem hast du recht damit, überhitzte Elemente und Auswahl zu markieren. TODO – PhiLho

+0

Hinweis: Ich habe den obigen Code für eine modernere/korrekte Version bearbeitet. Ein Vorteil meines Ansatzes ist, dass er flexibler ist als JSeparator und keinen Slot benötigt. – PhiLho

Verwandte Themen