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

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

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

    zeyuphoenix

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

    表格(單元格合并)

    JTable的單個單元格最復(fù)雜的操作也就是Renderer渲染和Editor編輯,然后增加事件處理和懸浮框提示,最多再加點特殊顯示效果,在前面的例子里都已經(jīng)講過了,這里就剩下最后一個關(guān)于單元格的操作了,單元格的合并和拆分.

    JTable的單元格可編輯時可以把它看做一個JTextField,不可操作時可以看做一個JLabel,對于單元格的合并和拆分操作來說就是把JLabelJTextField進(jìn)行合并和拆分的過程.JTable單元格的合并簡單來說就是把你選定的要合并的單元格的邊線擦掉,然后調(diào)整寬度和高度,再在這幾個合并的單元格外圍畫一個新的邊線,然后設(shè)置JTableUI,刷新就可以了.

    先看完成后的界面:

    然后是工程的目錄結(jié)構(gòu):

    其中CustomCell就合并后的Cell,它儲存了當(dāng)前那幾個Cell被合并,以及合并后的寬和高用于計算.CustomCellRenderer就是合并后的CellRenderer,它用于合并后Cell內(nèi)容的顯示,CustomCellUI則是合并CellUI,這是主要的合并Cell用到的類,剩下的兩個接口ICellAttributeICellSpan則是合并Cell的接口,里面定義Cell增刪和更新的方法,SpanCellTablePanel類是因為做成的合并單元格JTable很難使用,提供的輔助類,傳入數(shù)據(jù)則把JTable創(chuàng)建出來,并根據(jù)數(shù)據(jù)實現(xiàn)了合并單元格.

    先看接口IcellSpan,它提供設(shè)置單元格是否可見,單元格的合并和拆分方法,單元格拆分的Index方法需要實現(xiàn)類完成.

    /**

     *theinterfacethataboutcellspan.

     */

    publicinterface ICellSpan {

    方法如下:

        /**

         *getcellSpan.

         */

        publicint[] getSpan(int row, int column);

        /**

         *setcellspan.

         */

        publicvoid setSpan(int[] span, int row, int column);

    這兩個方法是提供JTable真正的行和列和合并后的行和列的對應(yīng)關(guān)系.

        /**

         *iscellvisible.

         */

        publicboolean isVisible(int row, int column);

        /**

         *wherecombine.

         */

        publicvoid combine(int[] rows, int[] columns);

        /**

         *wheresplit.

         */

        publicvoid split(int row, int column);

    提供當(dāng)前Jtable那幾個行和列合并;以及合并后的某一行和列的拆分.

    然后是IcellAttribute接口,它提供增加行、增加列、以及插入行、取得和設(shè)置大小(不是物理大小,是相對于JTable的大小)的方法:

    /**

     *theinterfacethataboutcellattribute.

     */

    publicinterface ICellAttribute {

    再看方法:

        /**

         *addcolumntocell.

         */

        publicvoid addColumn();

        /**

         *addrowtocell.

         */

        publicvoid addRow();

        /**

         *insertrowtocell

         */

        publicvoid insertRow(int row);

    這三個方法提供行和列的增加操作

        /**

         *getcellsize.

         */

        public Dimension getSize();

        /**

         *setcellsize.

         */

        publicvoid setSize(Dimension size);

    這兩個方法提供單元格大小的設(shè)置和取得.

    再看實現(xiàn)這兩個接口的類CustomCell,它是合并后的單元格的信息保存類:

    /**

     *setcellAttributespanandsoon.

     */

    publicclass CustomCell implements ICellAttribute, ICellSpan {

    有三個屬性:

        /**cellwidth.*/

        privateintrowSize = 0;

        /**cellheight.*/

        privateintcolumnSize = 0;

        /**cellspans.*/

    privateint[][][] span = null;

    分別保存合并后單元格的寬度和高度(這個寬和高的意思是在兩個方向上有幾個JTable的單元格大小),以及合并的單元格是由原本JTable的那幾個行和列組成的.

    先是構(gòu)造函數(shù):

        /**

         *setcellattribute.

         */

        public CustomCell() {

            this(1, 1);

    }

    setSize(new Dimension(columnSize, rowSize));

    setSize方法里,初始化屬性:

        @Override

        publicvoid setSize(Dimension size) {

            columnSize = size.width;

            rowSize = size.height;

            span = newint[rowSize][columnSize][2];

            initValue();

        }

    然后是初始化方法,

        /**

         *setcellinit.

         */

        privatevoid initValue() {

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

                for (int j = 0; j < span[i].length; j++) {

                    span[i][j][ICellSpan.COLUMN] = 1;

                    span[i][j][ICellSpan.ROW] = 1;

                }

            }

    }

    然后就是實現(xiàn)接口的方法,

        @Override

    publicint[] getSpan(int row, int column) {

    返回span數(shù)組對應(yīng)的行和列:

    returnspan[row][column];

        @Override

    publicvoid setSpan(int[] span, int row, int column) {

    設(shè)置span數(shù)組對應(yīng)的行和列:

    this.span[row][column] = span;

        @Override

    publicvoid addColumn() {

        @Override

    publicvoid addRow() {

        @Override

    publicvoid insertRow(int row) {

    這三個方法很類似,都是先取得舊有的span

        int[][][] oldSpan = span;

        int numRows = oldSpan.length;

    int numColumns = oldSpan[0].length;

    然后創(chuàng)建新的:

    span = newint[numRows + 1][numColumns][2];

    System.arraycopy(oldSpan, 0, span, 0, numRows);

    最后賦予新的值:

        for (int i = 0; i < numColumns; i++) {

                span[numRows][i][ICellSpan.COLUMN] = 1;

                span[numRows][i][ICellSpan.ROW] = 1;

         }

    最后是比較重要的合并和拆分方法,它根據(jù)傳入的需要合并和拆分的行和列計算,得出數(shù)組新的值:

        @Override

    publicvoid combine(int[] rows, int[] columns) {

    先取得開始比較的起點:

            int rowSpan = rows.length;

            int columnSpan = columns.length;

            int startRow = rows[0];

            int startColumn = columns[0];

    對于需要修改的值比較并賦予新的:

          for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {

                for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {

                    span[startRow + i][startColumn + j][ICellSpan.COLUMN] = jj;

                    span[startRow + i][startColumn + j][ICellSpan.ROW] = ii;

                }

            }

    最后設(shè)置新的數(shù)組值:

            span[startRow][startColumn][ICellSpan.COLUMN] = columnSpan;

            span[startRow][startColumn][ICellSpan.ROW] = rowSpan;

    這樣新的span就形成了,當(dāng)畫面repaint,UI會根據(jù)新的span的值決定那個單元格的Border需要繪制,那個需要擦去,這樣就單元格方面完成了拆分,至于持分后內(nèi)容的顯示則是通過Rebderer控制的.

    這里我們的Rebderer類十分簡單,我們就不實現(xiàn)任何效果了,只確定合并后的顯示問題:

    publicclass CustomCellRenderer extends JLabel implements TableCellRenderer {

    它的接口實現(xiàn)方法

        @Override

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

    除了定義顏色背景色的基本屬性外,最主要的是設(shè)置顯示:

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

    然后就是很重要的CustomCellUI類了,它根據(jù)前面CustomCell類的span來繪制合并單元格后的顯示問題:

    /**

     *BasicTableUIimplementation,paintthespantableui.

     */

    publicclass CustomCellUI extends BasicTableUI {

    它重寫BasicTableUIpaint方法進(jìn)行自己的UI繪制,

        /**

         *Paintarepresentationofthetableinstancethatwasset

         *ininstallUI().

         */

        @Override

        publicvoid paint(Graphics g, JComponent c) {

    首先取得舊的繪制邊框:

           Rectangle oldClipBounds = g.getClipBounds();

           Rectangle clipBounds = new Rectangle(oldClipBounds);

    然后根據(jù)JTable的寬度比較決定繪制的寬度,

           int tableWidth = table.getColumnModel().getTotalColumnWidth();

           clipBounds.width = Math.min(clipBounds.width, tableWidth);

           g.setClip(clipBounds);

    取得行的邊框

           Rectangle rowRect = new Rectangle(0, 0, tableWidth, table

                  .getRowHeight() + table.getRowMargin());

           rowRect.y = firstIndex * rowRect.height;

    然后開始繪制行:

    先去的需要繪制的合并單元格的屬性:

           CustomTableModel tableModel = (CustomTableModel) table

                  .getModel();

           ICellSpan cellAtt = (ICellSpan) tableModel.getCellAttribute();

    然后算出本行內(nèi)那幾個列需要合并:

           cellRow = row + cellAtt.getSpan(row, column)[ICellSpan.ROW];

           cellColumn = column

                         + cellAtt.getSpan(row, column)[ICellSpan.COLUMN];

    最后就是繪制具體的單元格了:

           Color c = g.getColor();

           g.setColor(table.getGridColor());

           g.drawRect(cellRect.x, cellRect.y, cellRect.width - 1,

                  cellRect.height - 1);

           g.setColor(c);

           cellRect.setBounds(cellRect.x + spacingWidth / 2, cellRect.y

                  + spacingHeight / 2, cellRect.width - spacingWidth,

                  cellRect.height - spacingHeight);

    不僅如此還需要控制編輯狀態(tài)和普通狀態(tài)有Renderer的顯示問題:

            Component component = table.getEditorComponent();

           component.setBounds(cellRect);

           component.validate();

            //renderer

           rendererPane.paintComponent(g, component, table, cellRect.x,

               cellRect.y, cellRect.width, cellRect.height, true);

    到這里單元格合并后的顯示就完成了,還有就是JTable的顯示和TableModel的數(shù)據(jù)設(shè)置,先看TableModel:

    我們繼承DefaultTableModel,

    publicclass CustomTableModel extends DefaultTableModel {

    它的構(gòu)造函數(shù)和DefaultTableModel一樣,最終都會轉(zhuǎn)換為Vector,

    public CustomTableModel(Vector<Vector<?>> data, Vector<?> columnNames) {

           addDataVector(data, columnNames);

    }

    在它的addDataVector方法里,不但要給TableModel的數(shù)據(jù)集賦:

           dataVector = new Vector<Vector<?>>(0);

           setColumnIdentifiers(columnNames);

           dataVector = newData;

    還要根據(jù)行和列做成我們的CustomCell:

           cellAtt = new CustomCell (dataVector.size(), columnIdentifiers

                  .size());
    同樣的TableModeladdColumn、addRow、insertRow方法,我們都需要復(fù)寫修改,加上我們自己Cell的增加方法:

        cellAtt.addRow();

        cellAtt.insertRow(row);

        cellAtt.addColumn();

    最后我們修改的是JTable,我們繼承它,設(shè)置它的UI和鼠標(biāo)行和列的響應(yīng):

    publicclass CustomTabel extends JTable {

    構(gòu)造函數(shù)和JTable相同,只不過我們需要設(shè)置自己的UI,

    setUI(new CustomCellUI());

    然后復(fù)寫rowAtPointcolumnAtPoint得到鼠標(biāo)點擊時我們真正的行列:

        @Override

        publicint rowAtPoint(Point point) {

    首先是取得當(dāng)前所在行列和合并單元格的值:

        int row = point.y / (rowHeight + rowMargin);

        int column = getColumnModel().getColumnIndexAtX(point.x);

    ICellSpan cellAtt = (ICellSpan) ((CustomTableModel) getModel())

            .getCellAttribute();

    然后取得實際的:

        retValue[ICellSpan.COLUMN] = column

            + cellAtt.getSpan(row, column)[ICellSpan.COLUMN];

        retValue[ICellSpan.ROW] = row

            + cellAtt.getSpan(row, column)[ICellSpan.ROW];

    最后需要重寫的是方法,它保證了合并單元格后的行和列和Header的對應(yīng),不會因為去掉了單元格的Boder線使不能對齊:

     @Override

     public Rectangle getCellRect(int row, int column, boolean includeSpacing) {

    UI里的paint方法一樣就是計算補足沒有Border的間隙,一般每合并一個加上1就可以了.

    到這里為止,合并單元格的JTable就算完成了,但是比較麻煩的是因為它并不知道我們合并那個,不會主動給我們合并,需要我們自己去調(diào)用combine方法,比較復(fù)雜,而實際使用的時候,我們想告訴數(shù)據(jù)是什么樣子的希望JTable自己合并,因此寫了一個SpanCellTablePanel,只需傳入數(shù)據(jù)就可以自己合并了.

    publicclass SpanCellTablePanel extends JPanel {

    繼承Jpanel確保我們可以和一個普通的JPanel一樣使用它.

    它初始化TableModel并構(gòu)建了JTable:

    CustomTableModel model = new CustomTableModel(datas, convertToVector(columnTitle));

    CustomTabel table = new CustomTabel(model)

    提供了我們?nèi)〉?/span>JTable的方法:

        public JTable getTable() {

            returntable;

        }

    提供一個我們給定數(shù)據(jù)轉(zhuǎn)換為合并的數(shù)據(jù)的方法:

    privateint[][] combineSpanData(Vector<Vector<?>> datas) {

    然后根據(jù)數(shù)據(jù)合并單元格顯示出來:

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

                for (int t = 0; t < spanArray.length; t++) {

                    ((ICellSpan) cellAtt).combine(spanArray[t],

                                 newint[] { columns[i] });

                 }

            }

            table.clearSelection();

            table.revalidate();

            table.repaint();

       

    最后就是使用了,只需要要傳入我們的數(shù)據(jù)就可以構(gòu)建出可合并的JTable:

    spanTablePanel = new SpanCellTablePanel(createTestData());

    當(dāng)我們實際使用時可能希望選中任何一個單元格都選中目前處于的最大列全選擇,簡單的加個

    SelectionListener就可以了

    spanTablePanel.getTable().getSelectionModel().addListSelectionListener(

    在事件里處理選中:

        @Override

        publicvoid valueChanged(ListSelectionEvent e) {

             spanTablePanel.getTable().getSelectionModel()

                    .setSelectionInterval(allSelectRows[0],

                         llSelectRows[allSelectRows.length - 1]);

    到此為之,對單元格的操作就基本結(jié)束了,以后看到或者想到別的再補充,JTable剩下的比較復(fù)雜的就是JtableHeader,它也可以設(shè)置RendereEditor,也可以合并和拆分,可以設(shè)置特殊組件,下次就開始JtableHeader.

    posted on 2010-04-12 21:54 zeyuphoenix 閱讀(4222) 評論(0)  編輯  收藏 所屬分類: JTable的使用

    導(dǎo)航

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

    統(tǒng)計

    常用鏈接

    留言簿(52)

    隨筆分類

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲精品视频在线播放| 国产AV无码专区亚洲AWWW| 国产jizzjizz免费看jizz| 国产成人免费手机在线观看视频| 免费永久看黄在线观看app| 亚洲日韩中文字幕在线播放| 久久亚洲精品AB无码播放| 亚洲欧洲高清有无| 亚洲爆乳少妇无码激情| 免费在线人人电影网| 久久香蕉国产线看免费| 一个人免费观看www视频在线| 国产网站在线免费观看| 亚洲理论电影在线观看| 亚洲毛片基地日韩毛片基地| 羞羞视频免费观看| 青青草原1769久久免费播放| 毛片在线免费视频| 中文亚洲AV片在线观看不卡| 91精品国产亚洲爽啪在线影院 | 亚洲人成网址在线观看 | 国产成人精品日本亚洲专一区 | 国产亚洲视频在线播放大全| 成人妇女免费播放久久久| 国产精品久久免费| 亚洲国产欧美国产综合一区 | 最近中文字幕完整免费视频ww| 女人18毛片水最多免费观看| 中文字幕亚洲无线码| 亚洲a级成人片在线观看| 人人公开免费超级碰碰碰视频| 亚洲一区免费在线观看| 亚洲精品高清在线| 亚洲日韩国产精品无码av| 成人精品综合免费视频| 成年人视频免费在线观看| 亚洲熟女乱综合一区二区| 国产精品亚洲片在线va| a级片免费在线观看| 99精品视频在线视频免费观看 | 亚洲国产成人资源在线软件|