代码之家  ›  专栏  ›  技术社区  ›  Alfred B. Thordarson

如何将分隔符添加到Java中的JCOMBOBOX中?

  •  10
  • Alfred B. Thordarson  · 技术社区  · 16 年前

    我有一个 下拉框 希望在元素列表中有一个分隔符。如何在Java中实现这一点?

    一个很有用的示例场景是,在为字体系列选择制作组合框时,类似于Word和Excel中的字体系列选择控件。在这种情况下,我希望在顶部显示最常用的字体,然后显示一个分隔符,最后按字母顺序显示分隔符下面的所有字体系列。

    有人能帮助我做这件事吗?或者这在Java中是不可能的?

    3 回复  |  直到 9 年前
        1
  •  7
  •   pfranza Tom 'Blue' Piddock    16 年前

    有一个很短的教程,其中有一个示例,演示了如何在Java2s上使用自定义ListCellRenderer。 http://www.java2s.com/Code/Java/Swing-Components/BlockComboBoxExample.htm

    基本上,它涉及到在列表模型中插入一个已知的占位符,当您在ListCellRenderer中检测到该占位符时,将返回“new jseparator(jseparator.horizontal)”的实例。

        2
  •  4
  •   PhiLho    13 年前

    当我编写和测试下面的代码时,你可能得到了很多更好的答案…
    我不介意,因为我喜欢这个实验/学习(在前摆上还是有点绿色)。

    [编辑]三年后,我的环保意识有所下降,我考虑到了Bobndrew的有效言论。我对刚刚工作的密钥导航没有问题(可能是一个JVM版本问题?).I改进了渲染器以显示高光。我使用了更好的演示代码。接受的答案可能更好(更标准),如果您想要自定义分隔符,我的可能更灵活…

    基本思想是为组合框的项使用渲染器。对于大多数项目,它是一个简单的带有项目文本的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);
          }
        });
      }
    }
    
        3
  •  2
  •   macbirdie    16 年前

    您可以使用自定义 ListCellRenderer 这将以不同的方式绘制分隔符项。见 docs 和一个小 tutorial .