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

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

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

    zeyuphoenix

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

    JTable的表頭合并

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

    JTableHeader的單個表頭可編輯時可以把它看做一個JTextField,不可操作時可以看做一個JLabel,對于表頭的合并和拆分操作來說就是把JLabelJTextField進行合并和拆分的過程.JTable表頭的合并簡單來說就是把你選定的要合并的表頭的邊線擦掉,然后調整寬度和高度,再在這幾個合并的表頭外圍畫一個新的邊線,然后設置JTableHeaderUI,刷新就可以了,JTable的單元格基本相同,唯一的區別就是JTableHeader的表頭不像單元格那個容易得到和處理,我們需要定義數據結構來存儲它.

    先看完成后的效果:

    首先是合并一行的多個單元格為一個的界面:

    再就是多行多列的合并了:

    這兩個例子,實現是一樣的只是因為數據結構不一樣.

    最后一個則是和前面單元格合并組成的例子,我們綜合前面的單元格合并,結合這次的JTableHeader合并,做一個綜合的合并的例子:

    然后看工程的目錄:

    首先的定義一個數據結構,存儲我們合并的JTableHeader.

    需要理解的是,雖然看到的是一個大的單元格,但是其實它也是幾個JTableHeader,只是去掉了其內的邊框.所以對我們的合并的JTableHeader來說,需要定義一個數據結構來存儲它們的最小分子,當然它們的Renderer也存儲了,

    /**

     *thetableheaderthathavecolumngroup.

    */

    publicclass ColumnGroup {

    看它的屬性:

        /**headerrenderer.*/

        private TableCellRenderer renderer = null;

    這個是合并的JTableHeaderRenderer,這里我們簡單化,我們就不像前面寫RendererEditor那樣分開存儲了,我們假設這個JTableHeader使用同一類的Renderer,如果你想實現不一樣的Renderer,你可以把它們定義成數組(PS:這樣效果會比較怪異,一個合并的單元格包含了幾個組件).

        /**theheadergroup.*/

        private Vector<Object> vector = null;

    這個是合并的單元格的各個實際的最小單元格存儲結構.

        /**headervalue.*/

        private String text = null;

    這個是合并后單元格顯示的文本信息

        /**thehiddenborderwidth*/

        privateintmargin = 0;

    這個是合并的單元格內部兩個最小JTableHeader的間隙,其實就是去掉線后那個Border.

    除了提供各個屬性的GetSet方法外,還提供了增加單元格add

        /**

         *addheaderorgrouptocolumngroup.

         */

        publicvoid add(Object obj) {

           if (obj == null) {

               return;

           }

           v.addElement(obj);

        }

    取得合并后的單元格的大小getSize:

        /**

         *getheadergroupsize.

         */

        public Dimension getSize(JTable table) {

    這個方法需要計算,首先是取得一個沒有合并的最小單元格的JTableHeader的大小,通過Renderer取得組件:

           Component comp = renderer.getTableCellRendererComponent(table,

                  getHeaderValue(), false, false, -1, -1);

           int height = comp.getPreferredSize().height;

    寬度需要計算合并的還要加上間隙:

    Enumeration<Object> enumTemp = v.elements();

           while (enumTemp.hasMoreElements()) {

                  TableColumn aColumn = (TableColumn) obj;

                  width += aColumn.getWidth();

                  width += margin;

    最后取得這個合并的JTableHeader的大小:

           returnnew Dimension(width, height);

    還有一個比較重要的方法是根據JTable的某一列取得它的所有的包含列,這個主要用于繪制:

        public Vector<ColumnGroup> getColumnGroups(TableColumn column,

               Vector<ColumnGroup> group) {

    通過遞歸判斷列到底屬于那個ColumnGroup

        group.addElement(this);

           if (v.contains(column)) {

               return group;

           }

    沒有找的則是Null.

    然后我們看的類是MyTableColumn,它繼承于TableColumn,主要是JTableHeader的編輯屬性和Editor.

    publicclass MyTableColumn extends TableColumn {

    主要屬性:

        /**tableheadereditor.*/

        private TableCellEditor headerEditor;

        /**isheadereditable.*/

        privatebooleanisHeaderEditable;

    方法只是簡單的GetSet設置,設置了默認編輯與否和默認的JTableHeaderEditor.

    其實也是一個簡單的類,主要是描述JTableHeaderRenderer,這個在之前我們就介紹了,大概寫下:

    publicclass MyHeaderRenderer extends JLabel implements

            TableCellRenderer {

    實現默認的方法:

    @Override

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

    首先是取得JTableHeader:

           // set some color font about header.

           JTableHeader header = table.getTableHeader();

    設置屬性:

           setForeground(fgColor);

           setBackground(bgColor);

    setFont(header.getFont());

    還有設置高度,和前面的那個Renderer專題一樣:

           setPreferredSize(new Dimension(getWidth(), headerHeight));

    最后就是兩個最重要的類,JTableHeader和它的UI的繪制:

    先看UI,我們繼承于BasicTableHeaderUI:

    /**

     *BasicTableHeaderUIimplementation.

    */

    publicclass MyGroupTableHeaderUI extends BasicTableHeaderUI {

    它重寫BasicTableHeaderUIpaint方法進行自己的UI繪制,

        /**

         *Paintarepresentationofthetableinstancethatwasset

         *ininstallUI().

         */

        @Override

        publicvoid paint(Graphics g, JComponent c) {

    首先取得舊的繪制邊框:

           Rectangle oldClipBounds = g.getClipBounds();

           Rectangle clipBounds = new Rectangle(oldClipBounds);

    然后根據JTable的寬度比較決定繪制的寬度,

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

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

           g.setClip(clipBounds);

    取得行的邊框

           ((MyTableHeader) header).setColumnMargin();

           Dimension size = header.getSize();

    然后開始繪制行:

    先去的需要繪制的合并JTableHeader的屬性:

           Enumeration<?> cGroups = ((MyTableHeader) header)

                      .getColumnGroups(aColumn);

    然后算出本行內那幾個列需要合并:

           ColumnGroup cGroup = (ColumnGroup) cGroups.nextElement();

                      Rectangle groupRect = (Rectangle) h.get(cGroup);

                      if (groupRect == null) {

                         icount ++;

                         groupRect = new Rectangle(cellRect);

                         Dimension d = cGroup.getSize(header.getTable());

                         groupRect.width = d.width - icount;

                         groupRect.height = d.height;

                         h.put(cGroup, groupRect);

                      }

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

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

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

           TableCellRenderer renderer = cGroup.getHeaderRenderer();

          Component component = renderer.getTableCellRendererComponent(header

                  .getTable(), cGroup.getHeaderValue(), false, false, -1, -1);

           rendererPane.add(component);

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

                  cellRect.y, cellRect.width, cellRect.height, true);
    到這里JTableHeader合并后的顯示繪制就完成了,然后就是它的大小的顯示:

        @Override

        public Dimension getPreferredSize(JComponent c) {

           long width = 0;

           Enumeration<?> enumeration = header.getColumnModel().getColumns();

           while (enumeration.hasMoreElements()) {

               TableColumn aColumn = (TableColumn) enumeration.nextElement();

               width = width + aColumn.getPreferredWidth();

           }

           return createHeaderSize(width);

        }

    JTableHeader和單元格合并不同的一點是它的事件比較復雜,我們需要重寫寫它的MouseInputHandler

    /**

       *Thisinnerclassismarked&quot;public&quot;duetoacompilerbug. * Thisclassshouldbetreatedasa&quot;protected&quot;innerclass.

        *InstantiateitonlywithinsubclassesofBasicTableUI.

        */

    privateclass MouseInputHandler extends

               BasicTableHeaderUI.MouseInputHandler {

    它提供一個屬性,

           /**theshowcomponent.*/

           private Component dispatchComponent = null;

    然后在鼠標事件上加上我們自己的處理:

           @Override

           publicvoid mousePressed(MouseEvent e) {

    根據鼠標的位置取得我們合并后繪制的單元格:

               Point p = e.getPoint();

               TableColumnModel columnModel = header.getColumnModel();

               int index = columnModel.getColumnIndexAtX(p.x);

               if (index != -1) {

                  if (header.editCellAt(index, e)) {

                      setDispatchComponent(e);

    設置完我們的顯示后,再把事件下發:

               MouseEvent e2 = SwingUtilities.convertMouseEvent(header, e,

                      dispatchComponent);

               dispatchComponent.dispatchEvent(e2);

    其它的鼠標事件也一樣處理,添加我們自己的顯示.

    然后就是最重要的JTableHeader,我們重寫它:

    publicclass MyTableHeader extends JTableHeader implements CellEditorListener {

    重寫updateUI方法,設置我們自己的UI:

        @Override

        publicvoid updateUI() {

           setUI(new MyGroupTableHeaderUI());

           resizeAndRepaint();

           invalidate();

        }

    同時提供setColumnMarginaddColumnGroupsetCellEditor等方法設置JTableHeader的屬性和Editor.

    然后就是設置JTableHeader編輯狀態和編輯后狀態的設置了:

    首先根據鼠標事件取得是否是需要編輯的JTableHeader.

        publicboolean editCellAt(int index, EventObject e) {

    在可編輯的JTableHeader的單元格增加事件:

    TableCellEditor editor = getCellEditor(index);

           if (editor != null && editor.isCellEditable(e)) {

               editorComp = prepareEditor(editor, index);

               editorComp.setBounds(getHeaderRect(index));

               add(editorComp);

               editorComp.validate();

               setCellEditor(editor);

               setEditingColumn(index);

               editor.addCellEditorListener(this);

               returntrue;

           }

    重寫editingStopped方法和editingCanceled方法.編輯狀態停止后設置顯示:

        @Override

        publicvoid editingStopped(ChangeEvent e) {

           TableCellEditor editor = getCellEditor();

           if (editor != null) {

               Object value = editor.getCellEditorValue();

               int index = getEditingColumn();

               columnModel.getColumn(index).setHeaderValue(value);

               removeEditor();

           }

        }

        @Override

        publicvoid editingCanceled(ChangeEvent e) {

           removeEditor();

        }

    最后就是使用了,雖然JTableHeader設置已經很麻煩了,但是設置顯示數據更麻煩,因此不到萬不得已不要用了,它基本不支持,基本不可能通過后期數據生成,一般用也是做成報表之類,但報表的JasperReport做的更好,所以雖然在這里寫,只是算一個思路.

    使用首先要設置JTableHeader,構造JTableHeader的數據結構:

    @Override

        protected JTableHeader createDefaultTableHeader() {

            returnnew MyTableHeader(columnModel);

    }

    TableColumnModel cm = table.getColumnModel();

        ColumnGroup g_name = new ColumnGroup("Name");

        g_name.add(cm.getColumn(1));

    取得JTableHeader,設置合并的數據結構:

        MyTableHeader header = (MyTableHeader) table

           .getTableHeader();

    header.addColumnGroup(g_name);

    然后設置RendererUI

        TableCellRenderer renderer = new MyHeaderRenderer();

        model.getColumn(i).setHeaderRenderer(renderer);

    table.getTableHeader().setUI(new MyGroupTableHeaderUI());

    其它的就和一個普通的JTable一樣了.

    我們可以綜合單元格合并和JTableHeader合并,這樣就可以作出復雜的JTable,如上面最后那張圖.


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

    導航

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

    統計

    常用鏈接

    留言簿(52)

    隨筆分類

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲人成在线中文字幕| 亚洲熟妇AV一区二区三区宅男| 91香蕉国产线在线观看免费| 亚洲成年人电影在线观看| 在线观看免费毛片| 怡红院免费全部视频在线视频| 亚洲精品午夜在线观看| 日本媚薬痉挛在线观看免费| 中文日本免费高清| 国产成人精品日本亚洲专| 久久亚洲精品无码播放| 在线v片免费观看视频| a一级爱做片免费| 亚洲一区中文字幕| 国产亚洲精品精华液| 啦啦啦www免费视频| 美女视频黄的免费视频网页| 国内精品乱码卡1卡2卡3免费| 亚洲免费网站在线观看| 亚洲免费无码在线| AV片在线观看免费| 99热这里只有精品免费播放| 深夜a级毛片免费无码| 亚洲福利电影一区二区?| 亚洲AV无码乱码精品国产| 免费成人激情视频| 香蕉视频在线免费看| 亚洲av午夜国产精品无码中文字| 美女黄网站人色视频免费国产| 无码日韩精品一区二区三区免费| 国产午夜亚洲精品不卡| 亚洲一级毛片免费看| 亚洲Av永久无码精品三区在线 | 亚洲国产精品不卡毛片a在线| 最近中文字幕mv免费高清视频8| 一级**爱片免费视频| 亚洲AV噜噜一区二区三区| 亚洲免费电影网站| 精品日韩亚洲AV无码| 国产亚洲精品精华液| 亚洲精品无码Av人在线观看国产|