TWaver - 專注UI技術(shù)

          http://twaver.servasoft.com/
          posts - 171, comments - 191, trackbacks - 0, articles - 2
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          Swing探秘:編寫一個JCheckListBox組件

          Posted on 2010-08-23 13:56 TWaver 閱讀(2039) 評論(1)  編輯  收藏

          記得Delphi里面有一個TCheckListBox控件,是一個可打勾的列表。但是這個東西在Swing里面并沒有現(xiàn)成的。如今,我們就一起動手制作一個。根據(jù)Java的管理,就叫JCheckListBox吧。

          寫代碼之前,先考慮以下問題:

          • 繼承:當(dāng)然是從Swing的JList繼承。
          • 數(shù)據(jù)擴充:對于JList來說,它是顯示了一系列Object。無論其類型如何,都用一個默認的渲染器(DefaultListCellRenderer,從JLabel繼承而來)來畫,每個條目的文字用Object.toString()來設(shè)置。但是對于JCheckListBox來說,除了顯示文本外,還要考慮每個條目是否被選中,如果選中,要顯示“打勾”。所以,JList需要維護“每一個條目是否選中”的狀態(tài)信息。我們放在一個boolean數(shù)組中。
          • 渲染器:默認的Renderer肯定是不行了,無法顯示打勾。自然想到用JCheckBox來重新做一個渲染器,設(shè)置到JCheckListBox中。
          • 鼠標(biāo)監(jiān)聽器:現(xiàn)在可以畫每個條目了,但還不夠,必須能響應(yīng)鼠標(biāo)的點擊以便Check/UnCheck才行。所以要在JCheckListBox上加一個鼠標(biāo)監(jiān)聽器來響應(yīng)鼠標(biāo)事件。當(dāng)然,如果你想讓它相應(yīng)鍵盤輸入(例如Ctrl+A全選)也可如法炮制。
          • CheckListBoxModel:為了操作方便,這里還從AbstractListModel擴充一個CheckListBoxModel,它能在條目Check變化時發(fā)送事件。

          好了,由于代碼和原理都比較簡單,不再贅述,直接給出代碼,以及簡單注釋。

            1import java.awt.*;
            2import java.awt.event.*;
            3import javax.swing.*;
            4import javax.swing.event.*;
            5
            6public class JCheckListBox extends JList {
            7    //這個boolean數(shù)組裝載所有item是否被check的信息。
            8
            9    private boolean[] checkedItems = null;
           10
           11    /**
           12     * 定義一個簡單的ListModel,它可以發(fā)送check變化事件。
           13     */

           14    class CheckListBoxModel extends AbstractListModel {
           15
           16        private Object[] items = null;
           17
           18        CheckListBoxModel(Object[] items) {
           19            this.items = items;
           20        }

           21
           22        public int getSize() {
           23            return items.length;
           24        }

           25
           26        public Object getElementAt(int i) {
           27            return items[i];
           28        }

           29
           30        protected void fireCheckChanged(Object source, int index) {
           31            fireContentsChanged(source, index, index);
           32        }

           33
           34        public Object getItem(int index) {
           35            return items[index];
           36        }

           37    }

           38
           39    /**
           40     * 這里就覆蓋了一個構(gòu)造函數(shù)。其他JList你自己覆蓋吧,反正super一下再init就OK了。
           41     * @param items Object[]
           42     */

           43    public JCheckListBox(Object[] items) {
           44        setModel(new CheckListBoxModel(items));
           45        init();
           46    }

           47
           48    /**
           49     * 初始化控件。包括初始化boolean數(shù)組、安裝一個渲染器、安裝一個鼠標(biāo)監(jiān)聽器。
           50     */

           51    protected void init() {
           52        checkedItems = new boolean[this.getModel().getSize()];
           53        class MyCellRenderer extends JCheckBox implements ListCellRenderer {
           54
           55            public MyCellRenderer() {
           56                setOpaque(true);
           57            }

           58
           59            public Component getListCellRendererComponent(
           60                    JList list,
           61                    Object value,
           62                    int index,
           63                    boolean isSelected,
           64                    boolean cellHasFocus) {
           65                //這點代碼基本上從DefaultListCellRenderer.java中抄襲的。
           66                setComponentOrientation(list.getComponentOrientation());
           67                if (isSelected) {
           68                    setBackground(list.getSelectionBackground());
           69                    setForeground(list.getSelectionForeground());
           70                }
           else {
           71                    setBackground(list.getBackground());
           72                    setForeground(list.getForeground());
           73                }

           74
           75                if (value instanceof Icon) {
           76                    setIcon((Icon) value);
           77                    setText("");
           78                }
           else {
           79                    setIcon(null);
           80                    setText((value == null? "" : value.toString());
           81                }

           82                setEnabled(list.isEnabled());
           83                setFont(list.getFont());
           84
           85                //雖然抄襲,可這里別忘了設(shè)置check信息。
           86                this.setSelected(isChecked(index));
           87                return this;
           88            }

           89        }

           90
           91        this.setCellRenderer(new MyCellRenderer());
           92        //定義一個鼠標(biāo)監(jiān)聽器。如果點擊某個item,翻轉(zhuǎn)其check狀態(tài)。
           93        class CheckBoxListener extends MouseAdapter {
           94
           95            @Override
           96            public void mouseClicked(MouseEvent e) {
           97                int index = locationToIndex(e.getPoint());
           98                invertChecked(index);
           99            }

          100        }

          101
          102        this.addMouseListener(new CheckBoxListener());
          103    }

          104
          105    /**
          106     * 翻轉(zhuǎn)指定item的check狀態(tài)。
          107     * @param index int
          108     */

          109    public void invertChecked(int index) {
          110        checkedItems[index] = !checkedItems[index];
          111        //別忘了發(fā)送event。
          112        CheckListBoxModel model = (CheckListBoxModel) getModel();
          113        model.fireCheckChanged(this, index);
          114        this.repaint();
          115    }

          116
          117    /**
          118     * 是否指定item被check。
          119     * @param index int
          120     * @return boolean
          121     */

          122    public boolean isChecked(int index) {
          123        return checkedItems[index];
          124    }

          125
          126    /**
          127     * 獲得選中的item個數(shù)
          128     */

          129    public int getCheckedCount() {
          130        int result = 0;
          131        for (int i = 0; i < checkedItems.length; i++{
          132            if (checkedItems[i]) {
          133                result++;
          134            }

          135        }

          136        return result;
          137    }

          138
          139    /**
          140     * 所有選中item索引的數(shù)組。
          141     */

          142    public int[] getCheckedIndices() {
          143        int[] result = new int[getCheckedCount()];
          144        int index = 0;
          145        for (int i = 0; i < checkedItems.length; i++{
          146            if (checkedItems[i]) {
          147                result[index] = i;
          148                index++;
          149            }

          150        }

          151        return result;
          152    }

          153
          154    public static void main(String[] args) throws Exception {
          155
          156        Font font = new Font("微軟雅黑", Font.PLAIN, 12);
          157
          158        JFrame frame = new JFrame("TWaver中文社區(qū)之Swing探秘");
          159
          160        final JCheckListBox list = new JCheckListBox(new Object[]{"張三""李四""王二麻子""木頭六","小七子"});
          161        list.setFont(font);
          162        frame.getContentPane().add(new JScrollPane(list), BorderLayout.CENTER);
          163        JButton button = new JButton("OK");
          164        button.addActionListener(new ActionListener() {
          165
          166            public void actionPerformed(ActionEvent e) {
          167                System.exit(0);
          168            }

          169        }
          );
          170        frame.getContentPane().add(button, BorderLayout.SOUTH);
          171        final JLabel label = new JLabel("當(dāng)前沒有選擇。");
          172        label.setFont(font);
          173        list.getModel().addListDataListener(new ListDataListener() {
          174
          175            public void intervalAdded(ListDataEvent e) {
          176            }

          177
          178            public void intervalRemoved(ListDataEvent e) {
          179            }

          180
          181            public void contentsChanged(ListDataEvent e) {
          182                if (list.getCheckedCount() == 0{
          183                    label.setText("當(dāng)前沒有選擇。");
          184                }
           else {
          185                    String text = "當(dāng)前選擇:";
          186                    int[] indices = list.getCheckedIndices();
          187                    for (int i = 0; i < indices.length; i++{
          188                        text += ((CheckListBoxModel) list.getModel()).getItem(indices[i]).toString() + ",";
          189                    }

          190                    label.setText(text);
          191                }

          192            }

          193        }
          );
          194        frame.getContentPane().add(label, BorderLayout.NORTH);
          195        frame.setBounds(300300400200);
          196        frame.setVisible(true);
          197    }

          198}

          運行效果如下圖:


          評論

          # re: Swing探秘:編寫一個JCheckListBox組件  回復(fù)  更多評論   

          2010-08-24 09:25 by zeyuphoenix
          恩 以前我也寫過一個
          http://www.aygfsteel.com/zeyuphoenix/archive/2010/05/03/319976.html
          jlist是比較簡單的組件,基本不用考慮ui的問題,比jtable和jtree好處理,也沒什么高級擴展

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 吉水县| 连平县| 永定县| 贡觉县| 梁河县| 康乐县| 额尔古纳市| 庆城县| 响水县| 明光市| 景洪市| 旬邑县| 自贡市| 麻栗坡县| 临猗县| 武义县| 云和县| 二连浩特市| 铜鼓县| 霸州市| 科尔| 五指山市| 绥江县| 新安县| 广宁县| 太原市| 南川市| 扬中市| 泽库县| 将乐县| 元朗区| 嘉禾县| 社会| 云龙县| 屏东市| 环江| 青龙| 介休市| 安新县| 梨树县| 民权县|