首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

JTable 單元格跨列合併實作指南

     編輯:Java 程式設計入門

JTable 本身不支援單元格合併,但可透過自訂 TableModel、TableUI 並覆寫 getCellRect()、columnAtPoint()、rowAtPoint() 三個方法實現跨列合併。本文提供核心介面 CMap、擴充 CTable 類別與自訂 CTUI 渲染器的完整架構說明。

核心介面:CMap

package com.neuri.ctable;

public interface CMap {
    /** 取得指定儲存格跨越的列數 */
    int span(int row, int column);

    /** 取得覆蓋指定儲存格的可視儲存格列索引;若本身可視則回傳自身列索引 */
    int visibleCell(int row, int column);
}

擴充 JTable:CTable

package com.neuri.ctable;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;

public class CTable extends JTable {
    public CMap map;

    public CTable(CMap cmp, TableModel tbl) {
        super(tbl);
        map = cmp;
        setUI(new CTUI()); // 設定自訂 UI
    }

    @Override
    public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
        if (map == null) return super.getCellRect(row, column, includeSpacing);
        int visCol = map.visibleCell(row, column);
        Rectangle rect = super.getCellRect(row, visCol, includeSpacing);
        // 若跨列,累加後續列寬
        if (map.span(row, visCol) != 1) {
            for (int i = 1; i < map.span(row, visCol); i++) {
                rect.width += getColumnModel().getColumn(visCol + i).getWidth();
            }
        }
        return rect;
    }

    @Override
    public int columnAtPoint(Point p) {
        int col = super.columnAtPoint(p);
        if (col < 0) return col;
        int row = super.rowAtPoint(p);
        return map.visibleCell(row, col);
    }
}

自訂 TableUI:CTUI

繼承 javax.swing.plaf.basic.BasicTableUI,覆寫 paintComponent(Graphics g),利用 rendererPane 只繪製可視儲存格,略過被合併覆蓋的儲存格。

使用範例

// 實作 CMap,定義合併規則
CMap myMap = new CMap() {
    @Override public int span(int row, int col) {
        if (row == 0 && col == 0) return 3; // 第一儲存格跨 3 列
        return 1;
    }
    @Override public int visibleCell(int row, int col) {
        if (row == 0 && col > 0 && col < 3) return 0; // 第 1~2 列被第 0 列覆蓋
        return col;
    }
};

TableModel model = new DefaultTableModel(data, columnNames);
CTable table = new CTable(myMap, model);

注意事項:

  • 合併邏輯需同時處理模型資料與 UI 繪製,否則選取、編輯、滾動會出現異常。
  • 跨行合併需額外覆寫 rowAtPoint() 並擴充 CMap 介面。
  • 生產環境建議使用成熟庫(如 JIDE Grids、SwingX)以節省開發時間。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved