<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    zeyuphoenix

    愿我愛的人快樂,愿愛我的人快樂,為了這些,我愿意不快樂.

    表格(單元格放置組件)

    對于JTable單元格的渲染主要是通過兩個(gè)接口來實(shí)現(xiàn)的,一個(gè)是TableCellRenderer另一個(gè)是TableCellEditor,JTable默認(rèn)是用的是DefaultCellRendererDefaultCellEditor,這兩個(gè)都是在類似JTextfield的一個(gè)JComponent的基礎(chǔ)上來實(shí)現(xiàn)的,如果我們需要在JTable的單元格內(nèi)放置特殊的控件或者繪制出特殊的效果,就要實(shí)現(xiàn)TableCellRendererTableCellEditor接口,在其上繪制出自己需要的樣式,再通過JTablesetCellRenderersetCellEditor方法設(shè)置新的外觀呈現(xiàn).

    首先我們先看看TableCellRendererTableCellEditor接口的區(qū)別, TableCellRenderer接口就是用來繪制和展示當(dāng)前單元格的內(nèi)容的,可以用文字、圖片、組件、甚至Java2D來繪制效果; TableCellEditor主要是用來當(dāng)用戶點(diǎn)擊具體的某個(gè)單元格進(jìn)行編輯的時(shí)候來展現(xiàn)的,除了繪制之外,在點(diǎn)擊時(shí)還會有更加復(fù)雜的效果出現(xiàn).

    先看Sun官方給的簡單的例子,首先是TableCellRenderer

    運(yùn)行圖示如下:

    我們只需要實(shí)現(xiàn)TableCellRenderer就可以了,

    /**

     * This interface defines the method required by any object * that would like to be a renderer for cells in a JTable

     * in there, I put button in it.

    */

    publicclass MyButtonRenderer extends JButton implements TableCellRenderer {

    實(shí)現(xiàn)接口的方法:

        @Override

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

    然后設(shè)置屬性:

    setForeground(table.getSelectionForeground());

           setBackground(table.getSelectionBackground());

    setText((value == null) ? "" : value.toString());

    使用也很簡單,假如我們希望第一列是JButton,

    table.getColumnModel().getColumn(0).setCellRenderer(new MyButtonRenderer());

    接著是TableCellEditor的實(shí)現(xiàn),還是Sun給的例子:

    運(yùn)行圖示如下

    Sun公司在DefaultCellEditor類里提供了JComboBox參數(shù)的構(gòu)造函數(shù),直接使用就可以了.

       //Set up the editor for the sport cells.

       JComboBox comboBox = new JComboBox();

       comboBox.addItem("Snowboarding");

       comboBox.addItem("Rowing");

       comboBox.addItem("Knitting");

       comboBox.addItem("Speed reading");

       comboBox.addItem("Pool");

       comboBox.addItem("None of the above");

    table.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(comboBox));

    在這里看來,這個(gè)例子就可以了,但是它還是有問題的,什么問題呢,看下截圖:

    當(dāng)JTable的單元格比較短時(shí),下拉框顯示的內(nèi)容會出現(xiàn)不全的情況,需要修改一下:

    問題在哪兒呢,在于JComboboxUI,需要設(shè)置一下JCombobox的下拉菜單的寬度,具體實(shí)現(xiàn)在JCombobox那篇文章里已經(jīng)實(shí)現(xiàn)了,這里我們直接使用,

            String[] str = new String[] { "Snowboarding", "Rowing", "Knitting", "Speed reading", "None of the above" };

            MyComboBox combo = new MyComboBox(str);

            Dimension d = combo.getPreferredSize();

            combo.setPopupWidth(d.width);

            table.getColumnModel().getColumn(2).setCellEditor(newDefaultCellEditor(combo));

    運(yùn)行如下圖:

    到此為止,RendererEditor的簡單實(shí)用就完成了,這些例子都是Sun官方給的,我大概

    修改了一下,其實(shí)還有問題.

    讓我們回頭看第一個(gè)例子:

    當(dāng)鼠標(biāo)在JButton按下時(shí),如下圖:

    JButton的效果消失了,因?yàn)?/span>Renderer只是處理表示的樣式,對于可編輯的單元格就不可

    以了,編輯狀態(tài)下呈現(xiàn)的還是默認(rèn)的JTextField組件,所以對于可編輯的單元格,我們需

    要設(shè)置它的Editor.

    我們需要寫一個(gè)自己的Editor,為了簡單就不實(shí)現(xiàn)TableCellEditor接口了,只需要繼

    DefaultCellEditor.

    /**

     * The default editor for table and tree cells.

     */

    publicclass MyButtonCellEditor extends DefaultCellEditor {

     

    定義兩個(gè)屬性:

        //editor show

        private JButton button = null;

        //text

    private String label = null;

    分別代表編輯狀態(tài)下顯示的組件和顯示的值.

    然后重寫getTableCellEditorComponent方法,在編輯狀態(tài)表示我們自己的組件.

        /**

         * Sets an initial <code>value</code> for the editor.

         */

        @Override

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {

    設(shè)置組件樣式:

       button.setForeground(table.getSelectionForeground());

       button.setBackground(table.getSelectionBackground());

       label = (value == null) ? "" : value.toString();

       button.setText(label);

       returnbutton;

    然后還需要重寫getCellEditorValue方法,返回編輯完成后的值,

    @Override

        public Object getCellEditorValue() {

            returnnew String(label);

    }

    使用和以前設(shè)置RendererEditor一樣,設(shè)置2個(gè)就可以了.

    table.getColumnModel().getColumn(0).setCellRenderer(new MyButtonRenderer());

    table.getColumnModel().getColumn(0).setCellEditor(new MyButtonCellEditor());

    最后按下效果正常了:


    到此為止,簡單的RendererEditor就差不多了,但是我們在JTable放置的都是基本的Swing組件,可不可以放置復(fù)雜的呢,當(dāng)然是可以的,下面我們放置一個(gè)選擇組:

    如下圖:

    它也需要實(shí)現(xiàn)自己的RendererEditor,我們可以把這個(gè)顯示選擇按鈕組的單元格看做一個(gè)組件,當(dāng)然首先就是把這個(gè)組件作出來:

    /**

     * create the pane that some radio pane in it.

    */

    publicclass MyRadioPanel extends JPanel {

    它只有一個(gè)屬性,根據(jù)給定數(shù)組長度構(gòu)建Radio數(shù)組,

        /** radio button group. */

        private JRadioButton[] buttons = null;

    再看它的構(gòu)造函數(shù):

        public MyRadioPanel(String[] strButtonText) {

    我們在這里構(gòu)造JRadioButton

    buttons[i] = new JRadioButton(strButtonText[i]);

    加入到面板:

    add(buttons[i]);

    再添加取得和設(shè)置JRadioButton選擇的方法:

        /**

         * get button groups.

         */

        public JRadioButton[] getButtons() {

           returnbuttons;

        }

        /**

         * set which index select.

         */

        publicvoid setSelectedIndex(int index) {

           for (int i = 0; i < buttons.length; i++) {

               buttons[i].setSelected(i == index);

           }

        }

    然后就是寫Renderer,我們繼承MyRadioPanel并且實(shí)現(xiàn)TableCellRenderer接口就可以了.

    publicclass MyRadioCellRenderer extends MyRadioPanel implements

           TableCellRenderer {

    構(gòu)造函數(shù)直接使用MyRadioCellRenderer

        public MyRadioCellRenderer(String[] strButtonTexts) {

           super(strButtonTexts);

        }

    然后是實(shí)現(xiàn)接口的getTableCellRendererComponent方法:

        @Override

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

           if (value instanceof Integer) {

               setSelectedIndex(((Integer) value).intValue());

           }

           returnthis;

    }

    最后就是Editor,

    /**

     * create cell editor that radio in it.

    */

    publicclass MyRadioCellEditor extends DefaultCellEditor implements

           ItemListener {

    在它的構(gòu)造函數(shù)里我們?yōu)?/span>JRadioButton添加監(jiān)聽:

    JRadioButton[] buttons = panel.getButtons();

    buttons[i].addItemListener(this);

    在監(jiān)聽處理中我們停止編輯,

        @Override

        publicvoid itemStateChanged(ItemEvent e) {

           super.fireEditingStopped();

        }

    然后我們需要覆蓋DefaultCellEditorgetTableCellEditorComponent,返回我們需要顯示的MyRadioPanel.

        @Override

        public Component getTableCellEditorComponent(JTable table, Object value,

               boolean isSelected, int row, int column) {

           if (value instanceof Integer) {

               panel.setSelectedIndex(((Integer) value).intValue());

           }

           returnpanel;

        }

    最后我們重寫getCellEditorValue,返回編輯完成后我們顯示的值:

    @Override

        public Object getCellEditorValue() {

           returnnew Integer(panel.getSelectedIndex());

        }

    使用也很簡單,和前面設(shè)置RendererEditor一樣:

    String[] answer = { "A", "B", "C" };

    table.getColumnModel().getColumn(1).setCellRenderer(

          new MyRadioCellRenderer(answer));

    table.getColumnModel().getColumn(1).setCellEditor(

          new MyRadioCellEditor(newMyRadioCellRenderer(answer)));

    接下來我們看一個(gè)比較綜合的例子,首先還是從畫面開始:

    先從簡單的開始做起,首先使JTable的第三列顯示成進(jìn)度條,這個(gè)和前面的設(shè)置Renderer一樣,實(shí)現(xiàn)TableCellRenderer就可以了.

    /**

     * This interface defines the method required by any object * that would like to be a renderer for cells in a JTable

     * in there, I put progress bar in it.

    */

    publicclass MyProgressCellRenderer extends JProgressBar implements

           TableCellRenderer {

    它提供一個(gè)屬性放置各個(gè)顏色區(qū)間需要設(shè)置的顏色:

        /** the progress bar's color. */

        private Hashtable<Integer, Color> limitColors = null;

    在構(gòu)造函數(shù)里我們設(shè)置顯示的最大和最小值:

        /**

        * Creates a progress bar using the specified orientation, * minimum, and maximum.

         */

        public MyProgressCellRenderer(int min, int max) {

           super(JProgressBar.HORIZONTAL, min, max);

           setBorderPainted(false);

        }

    然后實(shí)現(xiàn)TableCellRenderer接口的getTableCellRendererComponent方法,設(shè)置顯示組件和顏色:

        @Override

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

    先根據(jù)單元格的值取得顏色:

            Color color = getColor(n);

           if (color != null) {

               setForeground(color);

           }

    同時(shí)設(shè)置JProcessBar的值并返回它.

           setValue(n);

           returnthis;

    最后還提供一個(gè)設(shè)置顏色的方法:

    publicvoid setLimits(Hashtable<Integer, Color> limitColors) {

    它把傳入的顏色表按照大小先排序,然后設(shè)置好.

    這樣一個(gè)簡單的顯示進(jìn)度條的TabelCellRenderer就完成了.然后通過setRenderer來使用它.

    //create renderer.

     MyProgressCellRenderer renderer = new MyProgressCellRenderer(

            MyProgressTableModel.MIN, MyProgressTableModel.MAX);

     renderer.setStringPainted(true);

     renderer.setBackground(table.getBackground());

     // set limit value and fill color

     Hashtable<Integer, Color> limitColors = new Hashtable<Integer, Color>();

     limitColors.put(new Integer(0), Color.green);

     limitColors.put(new Integer(20), Color.GRAY);

      limitColors.put(new Integer(40), Color.blue);

     limitColors.put(new Integer(60), Color.yellow);

     limitColors.put(new Integer(80), Color.red);

     renderer.setLimits(limitColors);

     //set renderer      table.getColumnModel().getColumn(2).setCellRenderer(renderer);

    然后我們需要考慮的是這個(gè)Renderer的值無法變化,只能根據(jù)初始化的時(shí)候的數(shù)值顯示,這明顯是不行的,所以我們考慮給JTable加上改變,改變第二列的數(shù)字,第三列進(jìn)度條隨之改變,如圖示:



    這時(shí)我們需要修改我們的TableModel,默認(rèn)的已經(jīng)無法滿足我們的需要了,我們需要自己寫一個(gè):

    publicclass MyProgressTableModel extends DefaultTableModel {

    在它的構(gòu)造函數(shù)里面,我們增加一個(gè)監(jiān)聽:

    this.addTableModelListener(new TableModelListener() {

               @Override

               publicvoid tableChanged(TableModelEvent e) {

    當(dāng)引起TableModel改變的事件是UPDATE時(shí)并且是第二列時(shí)候:

         //when table action is update.

        if (e.getType() == TableModelEvent.UPDATE) {

              int col = e.getColumn();

              if (col == 1) {

    我們?nèi)〉眯略O(shè)立的value,賦予第三列:

        //get the new set value.

        Integer value = (Integer) model.getValueAt(row, col);

        model.setValueAt(checkMinMax(value), row, ++col);

    重寫isCellEditable方法,設(shè)置可編輯的列:

        @Override

        publicboolean isCellEditable(int row, int col) {

           switch (col) {

           case 1:

               returntrue;

           default:

               returnfalse;

           }

        }

    重寫setValueAt方法,設(shè)置可賦予的值:

        @Override

        publicvoid setValueAt(Object obj, int row, int col) {

    這樣一個(gè)我們需要的TableModel就完成了,修改第二列的值,第三列進(jìn)度條也隨之改變,使用也很簡單:

            // set the table model.

            table.setModel(dm);

    就可以了.

    到這里,這個(gè)進(jìn)度條JTable基本完成了,但是在實(shí)際運(yùn)用中可能會出現(xiàn)這樣的問題:

    我們編輯JTable的時(shí)候給它的單元格賦予了一個(gè)不正常的值,導(dǎo)致顯示不正常,但是卻無法返回舊有的狀態(tài),這樣我們就需要再次改進(jìn)它:

    當(dāng)輸入錯(cuò)誤的值時(shí):

    然后可以返回以前的狀態(tài):

    這時(shí)候我們需要設(shè)置的是第二列的Editor,使它編輯狀態(tài)時(shí)可以驗(yàn)證我們的輸入,并觸發(fā):

    /**

     * Implements a cell editor that uses a formatted text

     * field to edit Integer values.

     */

    publicclass MyIntegerEditor extends DefaultCellEditor {

    它有一個(gè)參數(shù),用來處理編輯值的:

        //show component when cell edit

        private JFormattedTextField ftf;

    然后重寫DefaultCellEditorgetTableCellEditorComponent方法,返回我們定義的JFormattedTextField.

    JFormattedTextField ftf = (JFormattedTextField) super

    .getTableCellEditorComponent(table, value, isSelected, row, column); ftf.setValue(value);

    return ftf;

    重寫getCellEditorValue方法,保證我們返回值正確:

    getCellEditorValue

     @Override

        public Object getCellEditorValue() {

    取得編輯完成的值:

        Object o = ftf.getValue();

    判斷然后返回.

    然后重寫stopCellEditing方法,判斷編輯的值是否正確,不正確的情況下提示用戶,詢問用戶是返回還是重新設(shè)置.

        // Override to check whether the edit is valid,

        // setting the value if it is and complaining if it isn't.

        @Override

        publicboolean stopCellEditing() {

            JFormattedTextField ftf = (JFormattedTextField) getComponent();

            if (ftf.isEditValid()) {

                try {

                    ftf.commitEdit();

                } catch (java.text.ParseException exc) {

                }

            } else { // text is invalid

                if (!userSaysRevert()) {

                    // user wants to edit don't let the editor go away

                    returnfalse;

                }

            }

            returnsuper.stopCellEditing();

        }

    到目前為止,這個(gè)類基本完成了,但是只有焦點(diǎn)離開單元格才觸發(fā)驗(yàn)證事件,比較不和邏輯,我們加入一個(gè)鍵盤監(jiān)聽,回車也可以觸發(fā).

    ftf.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "check");

    ftf.getActionMap().put("check", new AbstractAction() {

    @Override

          publicvoid actionPerformed(ActionEvent e) {

               // The text is invalid.

               if (!ftf.isEditValid()) {

                   if (userSaysRevert()) {

                       // reverted inform the editor

                       ftf.postActionEvent();

                   }

                } else

                   try {

                       // The text is valid, so use it.

                       ftf.commitEdit();

                       // stop editing

                       ftf.postActionEvent();

                    } catch (java.text.ParseException exc) {

                    }

          }

    然后就可以使用它了,和前面設(shè)置一個(gè)Editor一樣:

       table.getColumnModel().getColumn(1).setCellEditor(

            new MyIntegerEditor(MyProgressTableModel.MIN,

                            MyProgressTableModel.MAX));

    到目前為止,JTableRendererEditor就完成了,實(shí)際使用中也就這樣了,但是還有一種特殊情況需要說一下,雖然這樣變態(tài)需求一般現(xiàn)實(shí)中很難碰到.上面我們所有的例子都是對某一個(gè)列來說的,但是如果有人需要第一行顯示正常單元格,第二行顯示JCombobox,第三行顯示JButton怎么處理呢.其實(shí)也相差不大,自己寫個(gè)RendererEditor,里面實(shí)現(xiàn)一個(gè)RendererEditor的序列,依次展現(xiàn)就可以了.

    先看圖:



    首先要做的寫一個(gè)類實(shí)現(xiàn)TableCellEditor接口,

    publicclass MyCellEditor implements TableCellEditor {

    它有兩個(gè)屬性:

        /** save all editor to it. */

        private Hashtable<Integer, TableCellEditor> editors = null;

        /** each cell editor. */

        private TableCellEditor editor = null;

    分別存儲了此Editor上所有的Editor隊(duì)列和當(dāng)前需要使用的Editor.

    再看它的構(gòu)造函數(shù),

        /**

         * Constructs a EachRowEditor. create default editor

         */

        public MyCellEditor(JTable table) {

    它初始化了Editor隊(duì)列

    editors = new Hashtable<Integer, TableCellEditor>();

    然后實(shí)現(xiàn)TableCellEditor接口的getTableCellEditorComponent方法

        @Override

        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {

    根據(jù)行號取得當(dāng)前單元格的Editor

    editor = (TableCellEditor) editors.get(new Integer(row));

    沒有的話,使用默認(rèn)的:

    if (editor == null) {

                editor = new DefaultCellEditor(new JTextField());

            }

    然后返回當(dāng)前Renderer下的單元格:

         returneditor.getTableCellEditorComponent(table, value, isSelected, row, column);

    接著實(shí)現(xiàn)stopCellEditingcancelCellEditingaddCellEditorListener

    removeCellEditorListenerisCellEditableshouldSelectCell方法,

    在這些方法里取得當(dāng)前那個(gè)單元格被編輯,取得正編輯的單元格的Editor,再調(diào)用Editor

    同樣的方法就可以了.

           if (e == null) {

              row = table.getSelectionModel().getAnchorSelectionIndex();

            } else {

                row = table.rowAtPoint(e.getPoint());

            }

            editor = (TableCellEditor) editors.get(new Integer(row));

            if (editor == null) {

                editor = new DefaultCellEditor(new JTextField());

            }

    最后提供一個(gè)設(shè)置單元格Editor的方法,

        /**

         * add cell editor to it.

         */

        publicvoid setEditorAt(int row, TableCellEditor editor) {

            editors.put(new Integer(row), editor);

        }

    這樣可以實(shí)現(xiàn)單元格級別的Editor就實(shí)現(xiàn)了,同樣的Renderer也一樣,同樣實(shí)現(xiàn)TableCellRenderer接口和它里面的方法就可以了,同樣用對列存儲每個(gè)單元格的Renderer,這里就不寫了.

    最后是使用:

    先創(chuàng)建JTable需要用到的Editor,再創(chuàng)建單一Cell用到的Editor,

     //create all cell editor

     MyCellEditor rowEditor = new MyCellEditor(table);

      //create cell editors

      MyButtonCellEditor buttonEditor = new MyButtonCellEditor();

     DefaultCellEditor comboBoxEditor = new

    DefaultCellEditor(comboBox);

    然后為需要的單元格設(shè)置Editor,

     //put cell editor in all cell editors

     rowEditor.setEditorAt(0, comboBoxEditor);

     rowEditor.setEditorAt(1, comboBoxEditor);

     rowEditor.setEditorAt(2, buttonEditor);

     rowEditor.setEditorAt(3, buttonEditor);

    最后設(shè)置JTableEditor,

     //set table editor

     table.getColumnModel().getColumn(0).setCellEditor(rowEditor);

    同樣的,RendererEditor完全一樣.這樣一個(gè)可以為具體單元格設(shè)置RendererEditor的例子就完成了.

    到此為止,關(guān)于在JTable的單元格放置組件的例子就全部完成了,總結(jié)起來也很簡單,就是設(shè)置RendererEditor,至于更復(fù)雜的效果,比如合并單元格之類的,就需要重寫JTableTableUI了,這就在以后說了

    posted on 2010-04-07 23:19 zeyuphoenix 閱讀(6333) 評論(0)  編輯  收藏 所屬分類: JTable的使用

    導(dǎo)航

    <2010年4月>
    28293031123
    45678910
    11121314151617
    18192021222324
    2526272829301
    2345678

    統(tǒng)計(jì)

    常用鏈接

    留言簿(52)

    隨筆分類

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲AV无码国产精品麻豆天美| 国产国产成年年人免费看片| 国产免费人人看大香伊| 国产日韩在线视频免费播放| 国产白丝无码免费视频| 在线观看免费污视频| 中文字幕一精品亚洲无线一区 | 国产色婷婷精品免费视频| 国产亚洲精品一品区99热| 亚洲AV无码无限在线观看不卡| fc2免费人成在线视频| 日韩国产免费一区二区三区| 亚洲国产主播精品极品网红| 亚洲网站在线免费观看| 永久免费精品影视网站| 无码乱肉视频免费大全合集| 国产亚洲一区二区三区在线不卡 | 亚洲欧洲高清有无| 一区二区免费在线观看| 91香蕉成人免费网站| 国产91免费在线观看| 亚洲欧洲日产国码一级毛片| 亚洲一本之道高清乱码| 伊人免费在线观看高清版| 色吊丝最新永久免费观看网站| 337p日本欧洲亚洲大胆色噜噜| 免费国产在线精品一区| 一道本不卡免费视频| 成人免费毛片内射美女-百度| 亚洲人成精品久久久久| 激情小说亚洲图片| 日本成年免费网站| 亚洲av无码成h人动漫无遮挡 | 亚洲人成伊人成综合网久久久| 亚洲欧美日韩国产成人| 亚洲美国产亚洲AV| 8x8×在线永久免费视频| 亚洲人成伊人成综合网久久久 | 国产精品无码一二区免费| 亚洲欧洲在线播放| 午夜不卡久久精品无码免费|