Java图形化界面编程超详细知识点(8)——列表框

目录

5 JList、JCpmboBox实现列表框

5.1 简单列表框

5.2 不强制存储列表项的ListModel和ComboBoxMedel

5.3 强制存储列表项的DefaultListModel和DefaultComboBoxModel

5.4 使用ListCellRenderer改变列表外观


5 JList、JCpmboBox实现列表框

        无论从哪个角度来看,JList和JComboBox都是极其相似的,他们都有一个列表框,只是JComboBox的列表框需要以下拉方式显示出来;JList和JComboBox都可以通过调用setRenderer()方法来改变列表项的表现形式。甚至维护这两个组件的Model都是相似的,JList使用ListModel,JComboBox使用ComboBoxModel,而ComboBoxModel是ListModel的子类。

5.1 简单列表框

使用JList或JComboBox实现简单列表框的步骤:

1.创建JList和JComboBox实现简单列表框的步骤:

JList(final E[ ] listData);创建JList对象,把listData数组中的每项内容转换成一个列表项显示

JList(final Vector<? extends E> listData);创建JList对象,把listData数组中的每项内容转换成一个列表项展示

JComboBox(E[ ] items);

JComboBox(Vector<E> items);

2.设置JList或JComboBox的外观行为

---------------------------------------JList--------------------------------------------------------------

addSelectionInterval(int anchor,int lead);在已经选中列表项的基础上,增加选中从anchor到lead索引范围内的所有列表项

setFixedCellHeight(int hight)/setFixedCellWidth(int width);设置列表项的高度和宽度

setLayoutOrientation(int layoutOrientation);设置列表框的布局方向

setSelectedIndex(int index);默认选中项

setSelectedIndices(int [ ] indices);设置默认选中的多个列表项

setSelectedValue(Object anObject,boolean shouldScroll);设置默认选中项,并滚动到该项显示

setSelectionBackground(Color selectionBackground);设置选中项的背景颜色

setSelectionForeground(Color selectionForeground);设置选中项的前景色

setSelectionInterval(int anchor,int lead);设置从anchor到lead范围内的所有列表项被选中

setSelectionMode(int selectionMode);设置选中模式,默认没有限制,也可以设置为单选或者区域选中

setVisibleRowCount(int visibleRowCount);设置列表框的可视高度足以显示多少行列表项

---------------------------------------JComboBox---------------------------------------------------- 

setEditable(boolean aFlag);设置是否可以直接修改列表文本框的值,默认为不可以

setMaximumRowCount(int count);设置列表框的可视高度足以显示多少行列表项

setSelectedIndex(int anIndex);设置默认选中项

setSelectedItem(Object anObject);根据列表项的值,设置默认选中项

3.设置监听器,监听列表变化,JList通过addListSelectionListener完成,JComboBox通过addItemListener完成。

案例:

        

public class ListTest {
    JFrame jf = new JFrame("列表框测试");
    String[] books = {"java自学宝典","轻量级javaEE企业应用实战","Android基础教程","jQuery实战教程","SpringBoot企业级开发"};

    //定义 布局选择按钮 所在的面板
    JPanel layoutPanel = new JPanel();
    ButtonGroup layoutGroup = new ButtonGroup();

    //定义 选择模式按钮 所在面板
    JPanel selectModePanel = new JPanel();
    ButtonGroup selectModeGroup = new ButtonGroup();

    JTextArea favorite = new JTextArea(4,40);


    //用一个字符串数组来创建一个JList对象
    JList<String> bookList ;
    JComboBox<String> bookSelector;

    public void init(){
        //组装视图

        //组装Jlist相关内容
        bookList = new JList<>(books);

        addBtn2LayoutPanel("纵向滚动",JList.VERTICAL);
        addBtn2LayoutPanel("纵向换行",JList.VERTICAL_WRAP);
        addBtn2LayoutPanel("横向换行",JList.HORIZONTAL_WRAP);

        addBtn2SelectModelPanel("无限制",ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        addBtn2SelectModelPanel("单选",ListSelectionModel.SINGLE_SELECTION);
        addBtn2SelectModelPanel("单范围",ListSelectionModel.SINGLE_INTERVAL_SELECTION);

        //对JList做设置
        bookList.setVisibleRowCount(3);
        bookList.setSelectionInterval(2,4);

        //处理条目选中事件
        bookList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                //获取当前选中的条目
                List<String> selectedValuesList = bookList.getSelectedValuesList();
                //把当前条目的内容设置到文本域中。
                favorite.setText("");
                for (String str : selectedValuesList) {
                    favorite.append(str+"\n");
                }
            }
        });

        Box bookListVBox = Box.createVerticalBox();
        bookListVBox.add(new JScrollPane(bookList));
        bookListVBox.add(layoutPanel);
        bookListVBox.add(selectModePanel);

        //组装JComboBox
        Vector<String> vector = new Vector<>();
//        List<String> list = List.of("java自学宝典", "轻量级javaEE企业应用实战", "Android基础教程", "jQuery实战教程", "SpringBoot企业级开发");
//        vector.addAll(list);
        for (int i = 0; i < books.length; i++) {
            vector.add(books[i]);
        }

        bookSelector = new JComboBox<>(vector);

        bookSelector.setEditable(true);

        bookSelector.setMaximumRowCount(4);

        bookSelector.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                //获取当前已经选中的条目,把内容设置到文本域中
                Object selectedItem = bookSelector.getSelectedItem();
                favorite.setText(selectedItem.toString());
            }
        });

        //组装顶部的左右两部分
        Box topBox = Box.createHorizontalBox();
        topBox.add(bookListVBox);
        JPanel bookSelectPanel = new JPanel();
        bookSelectPanel.add(bookSelector);
        topBox.add(bookSelectPanel);

        //组装底部
        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout(new BorderLayout());

        bottomPanel.add(new JLabel("您最喜欢的图书:"),BorderLayout.NORTH);
        bottomPanel.add(favorite);

        //组装整体
        Box holeBox = Box.createVerticalBox();
        holeBox.add(topBox);
        holeBox.add(bottomPanel);

        jf.add(holeBox);


        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.pack();
        jf.setVisible(true);

    }

    //封装方法,往layoutPanel中添加单选按钮
    public void addBtn2LayoutPanel(String name,int layoutType){
        //设置标题边框
        layoutPanel.setBorder(new TitledBorder(new EtchedBorder(),"确定选项布局"));

        //创建单选按钮
        JRadioButton button = new JRadioButton(name);

        layoutPanel.add(button);

        //让第一个按钮默认选中
        if (layoutGroup.getButtonCount()==0){
            button.setSelected(true);
        }

        layoutGroup.add(button);

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                bookList.setLayoutOrientation(layoutType);
            }
        });
    }

    //封装方法,给selectModelPanel添加按钮
    public void addBtn2SelectModelPanel(String name,int selectionModel){
        //设置标题边框
        selectModePanel.setBorder(new TitledBorder(new EtchedBorder(),"确定选择模式"));

        //创建单选按钮
        JRadioButton button = new JRadioButton(name);

        selectModePanel.add(button);

        //让第一个按钮默认选中
        if (selectModeGroup.getButtonCount()==0){
            button.setSelected(true);
        }

        selectModeGroup.add(button);

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
               bookList.setSelectionMode(selectionModel);
            }
        });
    }
    public static void main(String[] args) {
        new ListTest().init();
    }
}

5.2 不强制存储列表项的ListModel和ComboBoxMedel

        与ProgressBar一样,JList和JComboBox也采用了MVC设计模式,JList和JComboBox只负责外观的显示,而组件底层的状态数据则由对应的Model来维护,JList对应的Model是ListModel接口,JComboBox对应的Model是ComboBox接口,其代码如下:

public interface ListModel<E>
{
  int getSize();
  E getElementAt(int index);
  void addListDataListener(ListDataListener l);
  void removeListDataListener(ListDataListener l);
}

public interface ComboBoxModel<E> extends ListModel<E> {
  void setSelectedItem(Object anItem);
  Object getSelectedItem();
}

        从上面接口来看,这个ListModel不管JList里的所有列表项的存储形式,它甚至不强制存储所有的列表项,只要ListModel的实现类提供了getSize()和getElementAt()两个方法,JList就可以根据该ListModel对象来生成列表项。ComboBoxModel继承了ListModel,它添加了“选择项”的概念,选择项代表JComboBox显示区域内可见的列表项。

        在使用JList和JComboBox时,除了可以使用jdk提供的Model实现类,程序员自己也可以根据需求,自己定义Model的实现类,实现对应的方法使用。

案例:

        自定义NumberListModel和NumberComboBoxModel实现类,允许使用数据范围来创建JList和JComboBox:

public class NumberListModel extends AbstractListModel<BigDecimal> {
    BigDecimal start;
    BigDecimal end;
    BigDecimal step;

    public NumberListModel(BigDecimal start, BigDecimal end, BigDecimal step) {
        this.start = start;
        this.end = end;
        this.step = step;
    }


    @Override
    public int getSize() {
        int floor = (int) Math.floor(end.subtract(start).divide(step,2, RoundingMode.HALF_DOWN).doubleValue());
        return floor+1;
    }

    @Override
    public BigDecimal getElementAt(int index) {
        BigDecimal ele = new BigDecimal(index).multiply(step).add(start).setScale(2, RoundingMode.HALF_DOWN);
        return ele;
    }
}
public class NumberComboBoxListModel extends NumberListModel implements ComboBoxModel<BigDecimal> {
    //当前选中条目的索引
    private int selectedId;


    public NumberComboBoxListModel(BigDecimal start, BigDecimal end, BigDecimal step) {
        super(start, end, step);
    }

    @Override
    public void setSelectedItem(Object anItem) {

        if (anItem instanceof BigDecimal){
            BigDecimal curr = (BigDecimal) anItem;
            selectedId = curr.subtract(super.start).divide(super.step,2, RoundingMode.HALF_DOWN).intValue();
        }
    }

    @Override
    public Object getSelectedItem() {

        BigDecimal item = new BigDecimal(selectedId).multiply(super.step).add(super.start).setScale(1, RoundingMode.HALF_DOWN);

        return item;
    }
}
public class ListModelTest {
    JFrame jf = new JFrame("测试ListModel");
    JList<BigDecimal> jList = new JList<>(new NumberListModel(new BigDecimal(1),new BigDecimal(21),new BigDecimal(2)));

    JComboBox<BigDecimal> jComboBox = new JComboBox<>(new NumberComboBoxListModel(new BigDecimal(0.1),new BigDecimal(1.2),new BigDecimal(0.1)));

    JLabel label = new JLabel("您选择的值是:");

    JTextField jTextField = new JTextField(15);

    public void init(){
        //组装视图

        //组装顶部
        jList.setVisibleRowCount(4);
        jList.setSelectionInterval(2,4);

        jList.setFixedCellWidth(90);
        jList.setFixedCellHeight(30);

        jList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                List<BigDecimal> selectedValuesList = jList.getSelectedValuesList();
                jTextField.setText("");
                for (BigDecimal item : selectedValuesList) {
                    jTextField.setText(jTextField.getText()+item.toString()+",");
                }
            }
        });

        jComboBox.setMaximumRowCount(4);
        jComboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                Object selectedItem = jComboBox.getSelectedItem();
                jTextField.setText(selectedItem.toString());
            }
        });

        Box hBox = Box.createHorizontalBox();
        hBox.add(new JScrollPane(jList));

        JPanel tempPanel = new JPanel();
        tempPanel.add(jComboBox);
        hBox.add(tempPanel);
        jf.add(hBox);

        //组装底部
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(label);
        bottomPanel.add(jTextField);

        jf.add(bottomPanel,BorderLayout.SOUTH);

        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.pack();
        jf.setVisible(true);

    }

    public static void main(String[] args) {
        new ListModelTest().init();
    }
}

5.3 强制存储列表项的DefaultListModel和DefaultComboBoxModel

        前面只是介绍了如何创建JList、JComboBox对象,当调用JList和JComboBox构造方法时传入数组或Vector作为参数,这些数组元素或集合元素将会作为列表项。当使用JList或JComboBox时常常还需要动态地增加、删除列表项,例如JCombox提供了下列方法完成增删操作:

addItem( E item);添加一个列表项

insertItemAt(E item,int index);向指定索引处插入一个列表项

removeAllItems();删除所有列表项

removeItem(Object anObject);删除指定列表项

removeItemAt(int anIndex);删除指定索引处的列表项

        JList并没有提供这些类似的方法,如果需要创建一个可以添加、删除列表项的JList对象,则应该在创建JList的显式使用DefaultListModel作为构造参数。因为DefaultListModel作为JList的Model,它负责维护JList组件的所有列表数据,所以可以通过向DefaultListModel中添加、删除元素来实现向JList对象中增加、删除列表项。

DefaultListModel提供了如下方法来添加、删除元素:

add(int  index,E element);在该ListModel的指定位置插入指定元素

addElement(E obj);将指定元素添加到该ListModel的末尾

insertElementAt(E obj,int index);在该ListModel的指定位置处插入指定元素

Object remove(int index);删除该ListModel中指定位置处的元素

removeAllElements();删除该ListModel中所有元素

removeElement(E obj);删除该ListModel中第一个与参数匹配的元素

removeElementAt(int index);删除该ListModel中指定索引处的元素

removeRange(int fromIndex,int toIndex);删除该ListModel中指定范围内的所有元素

set(int index,E element);将该ListModel指定索引处的元素替换成指定元素

setElement(E obj,int index);将该ListModel指定索引处的元素替换成指定元素

 案例:

        使用DefaultListModel实现下图效果:

public class DefaultListModelTest {

    JFrame jf = new JFrame("测试DefaultListModel");

    JTextField bookName = new JTextField(20);

    JButton removeBtn = new JButton("删除选中图书");

    JButton addBtn = new JButton("添加指定图书");

    //创建JList
    JList<String> bookList;

    DefaultListModel<String> model = new DefaultListModel<>();

    public void init(){
        //组装视图
        model.addElement("java自学宝典");
        model.addElement("轻量级JavaEE企业应用实战");
        model.addElement("Android基础教程");
        model.addElement("JQuery实战教程");

        bookList = new JList<>(model);

        //设置Jlist
        bookList.setVisibleRowCount(4);
        //设置单选
        bookList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        jf.add(new JScrollPane(bookList));

        //组装底部
        addBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String name = bookName.getText();
                if (!name.trim().equals("")){//不是空字符串才添加
                    model.addElement(name);
                }
            }
        });

        removeBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int selectedIndex = bookList.getSelectedIndex();

                if (selectedIndex>=0){
                    model.remove(selectedIndex);
                }
            }
        });


        JPanel bottomPanel = new JPanel();
        bottomPanel.add(bookName);
        bottomPanel.add(addBtn);
        bottomPanel.add(removeBtn);

        jf.add(bottomPanel,BorderLayout.SOUTH);


        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.pack();
        jf.setVisible(true);

    }

    public static void main(String[] args) {
        new DefaultListModelTest().init();
    }

}

5.4 使用ListCellRenderer改变列表外观

        前面程序中的JList和JComboBox采用的都是简单的字符串列表项,实际上,JList和JComboBox还可以支持图标列表项,如果在创建JList或JComboBox时传入图标数组,则创建的JList和JComboBox的列表项就是图标。

        如果希望列表项是更复杂的组件,例如,希望像QQ一样每个列表项既有图标,又有字符串,此时需要使用ListCellRenderer接口的实现类对象,自定义每个条目组件的渲染过程:

public interface ListCellRenderer<E>
{
    Component getListCellRendererComponent(
        JList<? extends E> list,//列表组件
        E value,//当前列表项的内容
        int index,//当前列表项的索引
        boolean isSelected,//当前列表项是否被选中
        boolean cellHasFocus);//当前列表项是否获取了焦点
}

        通过JList的setCellRenderer(ListCellRenderer<? super E> cellRenderer)方法 ,把自定义的ListCellRenderer对象传递给JList,就可以按照自定义的规则绘制列表项组件了。

案例:

        使用ListCellRenderer实现下图效果:

public class ListCellRendererTest {

    private JFrame mainWin = new JFrame("好友列表");

    private String[] friends = {
            "李清照",
            "苏格拉底",
            "李白",
            "弄玉",
            "虎头"
    };

    //定义一个JList对象
    JList friendsList = new JList(friends);

    public void init() {
        //组装视图
        //给JList设置ListCellRenderer对象,指定列表项绘制的组件
        friendsList.setCellRenderer(new MyRenderer());

        mainWin.add(friendsList);

        mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainWin.pack();
        mainWin.setVisible(true);

    }

    private class MyRenderer extends JPanel implements ListCellRenderer{
        private String name;
        private ImageIcon icon;

        //记录背景色
        private Color backGround;
        //记录前景色:文字的颜色
        private Color forceGround;


        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            //重置成员变量的值
           this.name = value.toString();
           this.icon = new ImageIcon("E:\\GUISwing\\img\\tree\\"+name+".gif");

           this.backGround = isSelected? list.getSelectionBackground() : list.getBackground();
           this.forceGround = isSelected? list.getSelectionForeground() : list.getForeground();

            return this;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(60,80);
        }

        //绘制列表项的内容
        @Override
        public void paint(Graphics g) {
            int imageWidth = icon.getImage().getWidth(null);
            int imageHeight = icon.getImage().getHeight(null);

            //填充背景矩形
            g.setColor(backGround);
            g.fillRect(0,0,getWidth(),getHeight());

            //绘制头像
            g.drawImage(icon.getImage(),this.getWidth()/2 -imageWidth/2 ,10,null);

            //绘制昵称
            g.setColor(forceGround);
            g.setFont(new Font("StSong",Font.BOLD,18));
            g.drawString(this.name,this.getWidth()/2 - this.name.length()*20/2,imageHeight+30);

        }
    }


    public static void main(String[] args) {
        new ListCellRendererTest().init();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小西瓜呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值