2008-09-26 28 views
10

Tôi có JComboBox và muốn có dấu phân cách trong danh sách các phần tử. Làm thế nào để làm điều này trong Java?Làm cách nào để thêm dấu phân cách vào JComboBox trong Java?

Một kịch bản mẫu trong đó có ích khi tạo hộp tổ hợp để chọn phông chữ cho gia đình; tương tự như font-family-selection-control trong Word và Excel. Trong trường hợp này, tôi muốn hiển thị các phông chữ được sử dụng nhiều nhất ở trên cùng, sau đó là dấu phân cách và cuối cùng là tất cả các họ phông chữ bên dưới dấu phân tách theo thứ tự bảng chữ cái.

Bất cứ ai có thể giúp tôi làm thế nào để làm điều này hoặc điều này là không thể trong Java?

Trả lời

7

Có một hướng dẫn khá ngắn với một ví dụ cho thấy làm thế nào để sử dụng một ListCellRenderer tùy chỉnh trên java2s http://www.java2s.com/Code/Java/Swing-Components/BlockComboBoxExample.htm

Về cơ bản nó liên quan đến cách chèn một placeholder được biết đến trong mô hình danh sách của bạn và khi bạn phát hiện các placeholder trong ListCellRenderer bạn trả lại một ví dụ về 'JSeparator mới (JSeparator.HORIZONTAL)'

+2

Lệnh 'BlockComboBoxExample' dụ phá vỡ con trỏ-key và hệ thứ nhất điều hướng phím chữ cái. Ví dụ của Santhosh Kumar [http://www.jroller.com/santhosh/entry/jcombobox%5Fitems%5Fwith%5Fseparators] dường như hoạt động tốt hơn. – bobndrew

2

Bạn có thể sử dụng tùy chỉnh ListCellRenderer để vẽ các mục ngăn cách khác nhau. Xem docs và một số nhỏ tutorial.

4

Khi tôi viết và thử nghiệm mã bên dưới, bạn có thể có nhiều câu trả lời tốt hơn ...
Tôi không quan tâm vì tôi thích thử nghiệm/học tập (vẫn còn một chút màu xanh lá cây trên mặt trước Swing).

[EDIT] Ba năm sau, tôi hơi xanh hơn một chút và tôi đã tính đến các nhận xét hợp lệ của bobndrew. Tôi không có vấn đề với điều hướng chính mà chỉ hoạt động (có lẽ nó là một vấn đề phiên bản JVM?). Tuy nhiên, tôi đã cải thiện trình kết xuất để hiển thị phần đánh dấu. Và tôi sử dụng một mã demo tốt hơn. Câu trả lời được chấp nhận có lẽ tốt hơn (tiêu chuẩn hơn), tôi có thể linh hoạt hơn nếu bạn muốn có dấu phân tách tùy chỉnh ...

Ý tưởng cơ bản là sử dụng trình kết xuất cho các mục của hộp tổ hợp. Đối với hầu hết các mục, nó là một JLabel đơn giản với văn bản của mục đó. Đối với mục gần đây nhất/được sử dụng nhiều nhất, tôi trang trí JLabel với một đường viền tùy chỉnh vẽ một đường ở dưới cùng của nó.

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

lớp Separator, có thể dày, với màu sắc tùy chỉnh vv

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

Kiểm tra lớp:

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

Biến tên của bạn không phải là điều tồi tệ nhất ở đây: Bạn đang phá vỡ toàn bộ combobox-item-selection: lựa chọn không được vẽ nữa và các ký tự đầu tiên-key-jumps bị hỏng. Và bạn nên định nghĩa 'm_combo' và' m_renderer' trong phạm vi nhỏ nhất có thể (trong 'public TestGui()'). Và không nên sử dụng glooooobal 'm_lastRecentIndex' cho lớp Renderer ** và ** lớp 'TestGui' (lớp này phải là lớp chính đơn độc, không phải là lớp con 'JFrame'). Nhưng tôi thích kiểu niềng răng! – bobndrew

+0

@bobndrew: này! Như tôi đã viết, tôi là một người mới vào thời điểm đó (3 năm rồi!). Trong số các tội lỗi bạn không chỉ ra, tôi có thể sử dụng một số mẫu thử Swing tôi tìm thấy và thậm chí tệ hơn, tôi đã không sử dụng SwingUtilities.invokeLater! Mã tôi hiện đang sử dụng nó, ít nhất (nhưng nó vẫn là một lớp con JFrame ...). Và m_lastRecentIndex là địa phương hơn ... Nhưng hầu hết những lời chỉ trích của bạn là về một lớp thử nghiệm nhanh chóng, không thực sự là mã sản xuất.Hôm nay, tôi chú ý nhiều hơn đến mã như vậy, như người mới có thể lấy cảm hứng từ nó ... :-) Ngoài ra, bạn là đúng về làm nổi bật các yếu tố lơ lửng và lựa chọn. TODO – PhiLho

+0

Lưu ý: Tôi đã chỉnh sửa mã ở trên để có phiên bản hiện đại/chính xác hơn. Một ưu điểm của cách tiếp cận của tôi là nó linh hoạt hơn (ít nhất là nhìn vào) so với JSeparator và nó không có một khe. – PhiLho

Các vấn đề liên quan