• JCombox作为容器构建复合组件


    JCombox是JSwing中比较常用的组件,它显示的是一个项列表,扩展的是ListModil模型,利用ListCellBenderer来绘制下拉的每个Item。 同时Jcombox也可以作为一个容器, 将JLable, JCheckbox等做为Item显示在下拉项中,构成一个复合组件。下面以下拉选项中是JCheckBox选项(如下图所示)来分析如何构建JCombox的组合组件。

     
    首先,JCombox是以ListCellBenderer接口来绘制下拉Item的,所以,Item由以前的String改成JComponent, 必须重新实现该接口,制作自己的Renderer。 ListCellRenderer接口就一个方法:getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {},
    其中,各个参数的定义如下:
    list: 正在绘制的JList, 比如下拉菜单
    value: 选中的Item的值,可以是string, 也可以是自己写的一个Item,用list.getModel().getElementAt(index) 返回的值;
    index: 选中的Item的索引,-1代表什么都不选择;
    isSelected: 该单元格/Item是否被选中;
    cellHasFocus: 该Item是否拥有焦点;
    ListCellRenderer的工作原理: 在绘制JList的每个Cell之前,它会去调用getListCellRendererComponent( ),得到一个Component,并
    将这个Component绘制在正确的位置.因为getListCellRendererComponent( )返回的是Component,所以我们几乎可以扩展任意一个Component,来改变JList,JComboBox等的外观(关于渲染器或者绘制器的原理和知识见如下文章:http://piscesky.iteye.com/blog/281996 http://www.java3z.com/cwbwebhome/article/pr/sw13.jsp)。
    实现自己的Renderer,需要extends你要放在下拉菜单中的JComponent, 并且implements ListCellRenderer接口,然后return自己。代码如下:
     1 public class ComboCheckBoxRenderer extends JCheckBox implements ListCellRenderer, Serializable
     2     {
     3         private DefaultListCellRenderer labelRenderer;
     4 
     5         public ComboCheckBoxRenderer()
     6         {
     7             super();
     8             setOpaque(true);
     9             setBorder(noFocusBorder);
    10         }
    11 
    12         public Component getListCellRendererComponent(
    13                 JList list,
    14                 Object value,
    15                 int index,
    16                 boolean isSelected,
    17                 boolean cellHasFocus)
    18         {
    19             ComboCheckBoxEntry item = (ComboCheckBoxEntry) value;
    20             if (item.key == KEY_TITLE)
    21             {
    22                 if (labelRenderer == null)
    23                     labelRenderer = new DefaultListCellRenderer();
    24                 return labelRenderer.getListCellRendererComponent(list, item.value, index, isSelected, cellHasFocus);
    25             }
    26 
    27             setComponentOrientation(list.getComponentOrientation());
    28             if (isSelected)
    29             {
    30                 setBackground(list.getSelectionBackground());
    31                 setForeground(list.getSelectionForeground());
    32             }
    33             else
    34             {
    35                 setBackground(list.getBackground());
    36                 setForeground(list.getForeground());
    37             }
    38 
    39             setSelected(item.checked);
    40             setText(item.value);
    41             setEnabled(list.isEnabled());
    42             if (isAllItemSelected() && item.key != KEY_ALL)
    43                 setEnabled(false);
    44             setFont(list.getFont());
    45             setBorder((cellHasFocus) ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
    46             
    47             return this;
    48         }
    49     }
     

     也可以加上提示为每个选项,比如39行改为如下,就可以实现当选择某个item时候,提示你已经选择该item。

    if(item.checked){
      list.setToolTipText(item.value + "have been selected");
    }
    setSelected(item.checked);

    其次, 定制符合特定的Item结构来满足你的下拉菜单的显示,代码如下:

    public class ComboCheckBoxEntry
        {
            boolean checked;
            Object key;
            String value;
    
            public ComboCheckBoxEntry(boolean checked, Object key, String value)
            {
                this.checked = checked;
                this.key = key;
                this.value = value;
            }
            
            public String toString()
            {
                return value == null ? "" : value;
            }
        }

    定制的Item结构也可以继承一些接口,来实现一些功能,比如实现SelectEnable接口,使得Item具有是否采用线的样式,其实不继承这个接口,直接在Item里面增加一个属性isLineEnabled也行:

    public interface LineEnable {
        public void setLineEnabled(boolean isLineEnabled);
        public boolean isLineEnabled();
    }
    
    
    public class MyComboBoxItem implements SelectEnable, LineEnable {
    
    /*对于特殊的JCombobox设置Item时,设置MyComboBoxItem就可以使Item具有选择可否和是否是线的样式.*/
    
        private Object comboxItem = null;
        boolean isLineEnabled = false;
    }

    最后,设置JCombox的UI来控制显示,代码如下:

    public class ComboCheckBoxUI extends MetalComboBoxUI
        {
            protected ComboPopup createPopup()
            {
                ComboCheckPopUp comboCheckPopUp = new ComboCheckPopUp(comboBox);
                list = comboCheckPopUp.getList();
                return comboCheckPopUp;
            }
    
            public class ComboCheckPopUp extends BasicComboPopup
            {
                public ComboCheckPopUp(JComboBox cBox)
                {
                    super(cBox);
                }
    
                @Override
                protected JList createList()
                {
                    final ComboBoxModel model = comboBox.getModel();
                    
                    // wrapper model 屏蔽Title Item Entry
                    final DefaultComboBoxModel wrapper = new DefaultComboBoxModel();
                    model.addListDataListener(new ListDataListener()
                    {
                        public void contentsChanged(ListDataEvent e)
                        {}
                        public void intervalAdded(ListDataEvent e)
                        {
                            ComboCheckBoxEntry item = (ComboCheckBoxEntry) model.getElementAt(e.getIndex0());
                            if (item.key != KEY_TITLE)
                                wrapper.addElement(item);
                        }
                        public void intervalRemoved(ListDataEvent e)
                        {
                            int index = e.getIndex0() - 1;
                            if (index >= 0 && index <= wrapper.getSize())
                                wrapper.removeElementAt(index);
                        }
                    });
    
                    return new JList(wrapper)
                    {
                        public void processMouseEvent(MouseEvent e)
                        {
                            if (e.isControlDown())
                            {
                                e = new MouseEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers()
                                        ^ InputEvent.CTRL_MASK, e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger());
                            }
                            super.processMouseEvent(e);
                        }
                    };
                }
    
                @Override
                protected int getPopupHeightForRowCount(int maxRowCount)
                {
                    int minRowCount = Math.min(maxRowCount, list.getModel().getSize());
                    int height = 0;
                    ListCellRenderer renderer = list.getCellRenderer();
                    Object value = null;
    
                    for (int i = 0; i < minRowCount; ++i)
                    {
                        value = list.getModel().getElementAt(i);
                        Component c = renderer.getListCellRendererComponent(list, value, i, false, false);
                        height += c.getPreferredSize().height;
                    }
    
                    return height == 0 ? 100 : height;
                }
    
                @Override
                protected MouseListener createListMouseListener()
                {
                    return new CheckBoxListMouseHandler();
                }
    
                protected class CheckBoxListMouseHandler extends MouseAdapter
                {
                    @Override
                    public void mousePressed(MouseEvent anEvent)
                    {
                        int index = list.getSelectedIndex();
                        ComboCheckBoxEntry item = (ComboCheckBoxEntry) list.getModel().getElementAt(index);
                        if (item == null)
                            return;
                        if (item.key == KEY_TITLE)
                            return;
                        if (isAllItemSelected() && item.key != KEY_ALL)
                            return;
                        if (item.key == KEY_ALL && item.checked == false)
                        {
                            ListModel mdl = list.getModel();
                            for (int i = 0; i < mdl.getSize(); i++)
                            {
                                ComboCheckBoxEntry entry = (ComboCheckBoxEntry) mdl.getElementAt(i);
                                if (entry.key == KEY_ALL || entry.key == KEY_TITLE)
                                    continue;
                                entry.checked = false;
                            }
                        }
    
                        boolean checked = !item.checked;
                        int size = list.getModel().getSize();
                        item.checked = checked;
                        updateListBoxSelectionForEvent(anEvent, false);
                        fireItemStateChanged(new ItemEvent(MultiSelectionComboBox.this, 0, null, 0));
                        Rectangle rect = list.getCellBounds(0, size - 1);
                        list.repaint(rect);
                    }
                }
            }
        }

    现在测试如下:

     1 public class TestJcombox {
     2 
     3     /**
     4      * @param args
     5      */
     6     public static void main(String[] args) {
     7         // TODO Auto-generated method stub
     8 
     9         JDialog jDialog = new JDialog();
    10         jDialog.setLayout(new FlowLayout());
    11         MultiSelectionComboBox multiSel = new MultiSelectionComboBox("", true);
    12         multiSel.addItem(1, "中国");
    13         multiSel.addItem(2, "印度");
    14         multiSel.addItem(3, "日本");
    15         jDialog.add(multiSel);
    16         jDialog.setSize(200, 300);
    17         jDialog.setVisible(true);
    18     }
    19 
    20 }

    就可以得到开篇图所说的效果。

     引文:

    http://www.cnblogs.com/zhangxz/archive/2012/10/11/2720241.html

    http://www.blogjava.net/zeyuphoenix/archive/2010/04/12/318014.html

    http://www.java3z.com/cwbwebhome/article/pr/sw13.jsp

    http://piscesky.iteye.com/blog/281996

    http://blog.csdn.net/tyro668/article/details/4246347

    http://blog.csdn.net/heruiup/article/details/5995697

  • 相关阅读:
    P5047 [Ynoi2019 模拟赛] Yuno loves sqrt technology II
    P4887 【模板】莫队二次离线(第十四分块(前体))
    SP20644 ZQUERY
    企业战略管理【0612】
    管理经济学【0812】
    商务沟通[0664]
    国际企业管理【0813】
    社区管理【0272】
    战略管理【1059】
    管理沟通【1279】
  • 原文地址:https://www.cnblogs.com/kangls/p/2972943.html
Copyright © 2020-2023  润新知