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

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

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

    zeyuphoenix

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

    表格(單元格放置組件)

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

    首先我們先看看TableCellRendererTableCellEditor接口的區別, TableCellRenderer接口就是用來繪制和展示當前單元格的內容的,可以用文字、圖片、組件、甚至Java2D來繪制效果; TableCellEditor主要是用來當用戶點擊具體的某個單元格進行編輯的時候來展現的,除了繪制之外,在點擊時還會有更加復雜的效果出現.

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

    運行圖示如下:

    我們只需要實現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 {

    實現接口的方法:

        @Override

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

    然后設置屬性:

    setForeground(table.getSelectionForeground());

           setBackground(table.getSelectionBackground());

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

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

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

    接著是TableCellEditor的實現,還是Sun給的例子:

    運行圖示如下

    Sun公司在DefaultCellEditor類里提供了JComboBox參數的構造函數,直接使用就可以了.

       //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));

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

    JTable的單元格比較短時,下拉框顯示的內容會出現不全的情況,需要修改一下:

    問題在哪兒呢,在于JComboboxUI,需要設置一下JCombobox的下拉菜單的寬度,具體實現在JCombobox那篇文章里已經實現了,這里我們直接使用,

            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));

    運行如下圖:

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

    修改了一下,其實還有問題.

    讓我們回頭看第一個例子:

    當鼠標在JButton按下時,如下圖:

    JButton的效果消失了,因為Renderer只是處理表示的樣式,對于可編輯的單元格就不可

    以了,編輯狀態下呈現的還是默認的JTextField組件,所以對于可編輯的單元格,我們需

    要設置它的Editor.

    我們需要寫一個自己的Editor,為了簡單就不實現TableCellEditor接口了,只需要繼

    DefaultCellEditor.

    /**

     * The default editor for table and tree cells.

     */

    publicclass MyButtonCellEditor extends DefaultCellEditor {

     

    定義兩個屬性:

        //editor show

        private JButton button = null;

        //text

    private String label = null;

    分別代表編輯狀態下顯示的組件和顯示的值.

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

        /**

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

         */

        @Override

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

    設置組件樣式:

       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);

    }

    使用和以前設置RendererEditor一樣,設置2個就可以了.

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

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

    最后按下效果正常了:


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

    如下圖:

    它也需要實現自己的RendererEditor,我們可以把這個顯示選擇按鈕組的單元格看做一個組件,當然首先就是把這個組件作出來:

    /**

     * create the pane that some radio pane in it.

    */

    publicclass MyRadioPanel extends JPanel {

    它只有一個屬性,根據給定數組長度構建Radio數組,

        /** radio button group. */

        private JRadioButton[] buttons = null;

    再看它的構造函數:

        public MyRadioPanel(String[] strButtonText) {

    我們在這里構造JRadioButton

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

    加入到面板:

    add(buttons[i]);

    再添加取得和設置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并且實現TableCellRenderer接口就可以了.

    publicclass MyRadioCellRenderer extends MyRadioPanel implements

           TableCellRenderer {

    構造函數直接使用MyRadioCellRenderer

        public MyRadioCellRenderer(String[] strButtonTexts) {

           super(strButtonTexts);

        }

    然后是實現接口的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 {

    在它的構造函數里我們為JRadioButton添加監聽:

    JRadioButton[] buttons = panel.getButtons();

    buttons[i].addItemListener(this);

    在監聽處理中我們停止編輯,

        @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());

        }

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

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

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

          new MyRadioCellRenderer(answer));

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

          new MyRadioCellEditor(newMyRadioCellRenderer(answer)));

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

    先從簡單的開始做起,首先使JTable的第三列顯示成進度條,這個和前面的設置Renderer一樣,實現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 {

    它提供一個屬性放置各個顏色區間需要設置的顏色:

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

        private Hashtable<Integer, Color> limitColors = null;

    在構造函數里我們設置顯示的最大和最小值:

        /**

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

         */

        public MyProgressCellRenderer(int min, int max) {

           super(JProgressBar.HORIZONTAL, min, max);

           setBorderPainted(false);

        }

    然后實現TableCellRenderer接口的getTableCellRendererComponent方法,設置顯示組件和顏色:

        @Override

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

    先根據單元格的值取得顏色:

            Color color = getColor(n);

           if (color != null) {

               setForeground(color);

           }

    同時設置JProcessBar的值并返回它.

           setValue(n);

           returnthis;

    最后還提供一個設置顏色的方法:

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

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

    這樣一個簡單的顯示進度條的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);

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



    這時我們需要修改我們的TableModel,默認的已經無法滿足我們的需要了,我們需要自己寫一個:

    publicclass MyProgressTableModel extends DefaultTableModel {

    在它的構造函數里面,我們增加一個監聽:

    this.addTableModelListener(new TableModelListener() {

               @Override

               publicvoid tableChanged(TableModelEvent e) {

    當引起TableModel改變的事件是UPDATE時并且是第二列時候:

         //when table action is update.

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

              int col = e.getColumn();

              if (col == 1) {

    我們取得新設立的value,賦予第三列:

        //get the new set value.

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

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

    重寫isCellEditable方法,設置可編輯的列:

        @Override

        publicboolean isCellEditable(int row, int col) {

           switch (col) {

           case 1:

               returntrue;

           default:

               returnfalse;

           }

        }

    重寫setValueAt方法,設置可賦予的值:

        @Override

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

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

            // set the table model.

            table.setModel(dm);

    就可以了.

    到這里,這個進度條JTable基本完成了,但是在實際運用中可能會出現這樣的問題:

    我們編輯JTable的時候給它的單元格賦予了一個不正常的值,導致顯示不正常,但是卻無法返回舊有的狀態,這樣我們就需要再次改進它:

    當輸入錯誤的值時:

    然后可以返回以前的狀態:

    這時候我們需要設置的是第二列的Editor,使它編輯狀態時可以驗證我們的輸入,并觸發:

    /**

     * Implements a cell editor that uses a formatted text

     * field to edit Integer values.

     */

    publicclass MyIntegerEditor extends DefaultCellEditor {

    它有一個參數,用來處理編輯值的:

        //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方法,判斷編輯的值是否正確,不正確的情況下提示用戶,詢問用戶是返回還是重新設置.

        // 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();

        }

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

    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) {

                    }

          }

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

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

            new MyIntegerEditor(MyProgressTableModel.MIN,

                            MyProgressTableModel.MAX));

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

    先看圖:



    首先要做的寫一個類實現TableCellEditor接口,

    publicclass MyCellEditor implements TableCellEditor {

    它有兩個屬性:

        /** save all editor to it. */

        private Hashtable<Integer, TableCellEditor> editors = null;

        /** each cell editor. */

        private TableCellEditor editor = null;

    分別存儲了此Editor上所有的Editor隊列和當前需要使用的Editor.

    再看它的構造函數,

        /**

         * Constructs a EachRowEditor. create default editor

         */

        public MyCellEditor(JTable table) {

    它初始化了Editor隊列

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

    然后實現TableCellEditor接口的getTableCellEditorComponent方法

        @Override

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

    根據行號取得當前單元格的Editor

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

    沒有的話,使用默認的:

    if (editor == null) {

                editor = new DefaultCellEditor(new JTextField());

            }

    然后返回當前Renderer下的單元格:

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

    接著實現stopCellEditingcancelCellEditingaddCellEditorListener

    removeCellEditorListenerisCellEditableshouldSelectCell方法,

    在這些方法里取得當前那個單元格被編輯,取得正編輯的單元格的Editor,再調用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());

            }

    最后提供一個設置單元格Editor的方法,

        /**

         * add cell editor to it.

         */

        publicvoid setEditorAt(int row, TableCellEditor editor) {

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

        }

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

    最后是使用:

    先創建JTable需要用到的Editor,再創建單一Cell用到的Editor,

     //create all cell editor

     MyCellEditor rowEditor = new MyCellEditor(table);

      //create cell editors

      MyButtonCellEditor buttonEditor = new MyButtonCellEditor();

     DefaultCellEditor comboBoxEditor = new

    DefaultCellEditor(comboBox);

    然后為需要的單元格設置Editor,

     //put cell editor in all cell editors

     rowEditor.setEditorAt(0, comboBoxEditor);

     rowEditor.setEditorAt(1, comboBoxEditor);

     rowEditor.setEditorAt(2, buttonEditor);

     rowEditor.setEditorAt(3, buttonEditor);

    最后設置JTableEditor,

     //set table editor

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

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

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

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

    導航

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

    統計

    常用鏈接

    留言簿(52)

    隨筆分類

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 免费看黄福利app导航看一下黄色录像| 久久国产亚洲精品麻豆| 67pao强力打造67194在线午夜亚洲| 国产免费久久久久久无码| 亚洲A∨精品一区二区三区| 国产亚洲人成在线影院| 免费人妻av无码专区| 免费一级全黄少妇性色生活片 | 午夜老司机永久免费看片| 亚洲成AV人片在线播放无码| 性xxxxx大片免费视频| 亚洲黄色免费电影| 韩国免费一级成人毛片| 亚洲人成影院在线高清| 天天天欲色欲色WWW免费| 亚洲av成人无码网站…| 亚洲欧洲中文日韩久久AV乱码 | 日韩人妻无码精品久久免费一 | 免费**毛片在线播放直播 | 日本在线免费观看| 7777久久亚洲中文字幕蜜桃| 无人影院手机版在线观看免费| 亚洲精品理论电影在线观看| 亚洲国产人成中文幕一级二级| 黄视频在线观看免费| 亚洲电影一区二区| 久久综合AV免费观看| 在线精品自拍亚洲第一区| 激情97综合亚洲色婷婷五| 99精品视频在线观看免费播放| 亚洲日本久久一区二区va| 深夜国产福利99亚洲视频| 国产麻豆一精品一AV一免费| 国产色在线|亚洲| 亚洲午夜无码片在线观看影院猛 | 国产大片线上免费看| 中文在线免费不卡视频| 亚洲伊人久久精品| 亚洲精品无码AV中文字幕电影网站| 免费观看91视频| 亚洲精品无码日韩国产不卡av|