- PR -

JTableのヘッダについて

投稿者投稿内容
hira
会議室デビュー日: 2003/10/07
投稿数: 6
投稿日時: 2003-10-07 17:54
初投稿させて頂きます、よろしくお願いいたします。

現在Swingを用いたテーブルの表示について作業を行っております。
このテーブルについて、ヘッダの複数段表示で悩んでおります。
最終的には行及び列のヘッダについて、二段や三段の表示を行いたいと考えているのですが、
よい方法がみつかりません。
サンプル等も発見はしたのですが、複雑でまだ理解出来てはいません。
自分の勉強不足なのですが、コツやポイント等でも結構ですので、
わかりやすくお教え頂ければと思います。

環境は、j2sdk1.4.1_03 を使用しております。
よろしくお願いいたします。
koe
大ベテラン
会議室デビュー日: 2003/07/13
投稿数: 198
投稿日時: 2003-10-07 20:43
プロフェッショナルJava(上)に載っている方法ですが、
自作のセルレンダラでJLabelを複数個縦に並べるという方法があります。

javax.swing.table.TableCellHeaderを実装して
javax.swing.JPanelを継承した自作のヘッダ描画クラスを作成します。
自作のヘッダ描画クラスでは以下のメソッドを定義します。
public Component getTableCellRendererComponent(JTable table, Object value,
 boolean isSelected, boolean hasFocus, int row, int column){
 removeAll();
 StringTokenizer tokenizer = new StringTokenizer((String) value, "\r\n");
 setLayout(new GridLayout(tokenizer.countTokens(), 1));
 while(tokenizer.hasMoreTokens()){
  JLabel label = new JLabel(tokenizer.nextToken(), JLabel.CENTER);
  LookAndFeel.installColorsAndFont(label, "TableHeader.background",
    "TableHeader.foreground", "TableHeader.font");
  add(label);
 }
 LookAndFeel.installBorder(this, "TableHeader.cellBorder");
 return this;
}

こうして定義したレンダラを、テーブルで以下のように使用します。
// 自作のレンダラ
MyITableHeader header = new MyTableHeader();
TableColumnModel tcm = table.getColumnModel();
TableColumn tc = tcm.getColumn(0);
tc.setHeaderRenderer(header);
こうすると、ヘッダレンダラを指定した列のヘッダを描画する時に自作のレンダラを
使うようになります。

この方法で感心したのは、"\r\n"で任意の改行が可能な点です。
例えば、テーブルモデル側でgetColumnName(0)を実行すると
"とても\r\n長い\r\nヘッダ"
と返ってくる場合、0番目のヘッダはちゃんと

とても
長い
ヘッダ

と表示してくれます。

ところで、Swingでこういう凝った事をしようとすると難しくなるので、
何か詳しい本でも買って読んだほうがいいと思います。
また、この説明で TableModel や TableColumnModel がなんなのか
よく分からないようでしたら、なおのことSwingの解説本を読むことをお勧めします。
何がお勧めかといわれると困りますが…
さくらば
大ベテラン
会議室デビュー日: 2002/11/12
投稿数: 145
投稿日時: 2003-10-08 03:13
こんにちは、さくらばです。

引用:

koeさんの書き込み (2003-10-07 20:43) より:
プロフェッショナルJava(上)に載っている方法ですが、
自作のセルレンダラでJLabelを複数個縦に並べるという方法があります。



もっと簡単に実現することができます。というのもほとんどの
Swing のコンポーネントは HTML を表示することができるからです。

以下のコードでは getColumnName メソッドで HTML を返すようにしています。
これだけで、3 行のヘッダが実現できます。

コード:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class MultiHeaderTest {
    public MultiHeaderTest() {
        JFrame frame = new JFrame("Multi Header Test");
        frame.setBounds(100, 100, 400, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JTable table = new JTable(new MyTableModel());
        frame.getContentPane().add(new JScrollPane(table));
        
        frame.setVisible(true);
    }

    class MyTableModel extends AbstractTableModel {
        private Object[][] values;

        public MyTableModel() {
            values = new Object[3][3];

            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    values[i][j] = new Integer(i*3 + j);
                }
            }
        }

        public int getRowCount() {
            return 3;
        }
        
        public int getColumnCount() {
            return 3;
        }
        
        public String getColumnName(int column) {
            return "<html><p>This is <br>" + column + "<br>Column Header</p></html>";
        }

        public Object getValueAt(int row, int column) {
            return values[row][column];
        }
    }

    public static void main(String[] args) {
        new MultiHeaderTest();
    }
}

koe
大ベテラン
会議室デビュー日: 2003/07/13
投稿数: 198
投稿日時: 2003-10-08 13:20
引用:

さくらばさんの書き込み (2003-10-08 03:13) より:
もっと簡単に実現することができます。というのもほとんどの
Swing のコンポーネントは HTML を表示することができるからです。


目から鱗でした。HTMLを表示できるということは知っていたのですが、
思い至りませんでした。
最初の質問者ではないですが、いいネタありがとうございます。

そういえば、JMenuItemのテキストをHTMLで与えて表示を飾り付ける、というのが
いつぞやのJavaWorldに載っていたような…。
hira
会議室デビュー日: 2003/10/07
投稿数: 6
投稿日時: 2003-10-08 13:22
koeさん、さくらばさん、ご返信頂き大変ありがとうございます。

ご質問させて頂いた事について補足をさせて頂きたいのですが、
私が考えているのはヘッダ自体のグループ化です。
イメージとしては、例えばRow Header であれば
------------
| 1 | 2  |
|   |    |
|   |-----|
|   | 3  |
|   |    |
------------

のような、複数のグループ化されたヘッダです。
サンプルまでつけて頂いたのですが、私の説明不足でした。
大変申し訳ございません。
ですが、ご指摘頂いたようにやはりまだ理解出来ていない部分が多々あるので、
Swingの解説本でもっと勉強したいと思います。ありがとうございます。

ちなみに、上記のヘッダの実現について、現段階ではセルの罫線を白紙にし
目的の形に引き直すという方法を考えているのですが、その方法を模索中です。
改めて、良い方法をご存知の方がいらっしゃいましたらアドバイス頂ければと思います。

度々申し訳ございませんが、よろしくお願いいたします。
さくらば
大ベテラン
会議室デビュー日: 2002/11/12
投稿数: 145
投稿日時: 2003-10-08 14:15
こんにちは、さくらばです。

引用:

hiraさんの書き込み (2003-10-08 13:22) より:
私が考えているのはヘッダ自体のグループ化です。
イメージとしては、例えばRow Header であれば
------------
| 1 | 2  |
|   |    |
|   |-----|
|   | 3  |
|   |    |
------------

のような、複数のグループ化されたヘッダです。



このページが参考になると思います。
http://www2.gol.com/users/tame/swing/examples/JTableExamples1.html

ただし、これらは作られてからずいぶんたっているのでそのままだと例外が発生してしまいます。

GroupableTableHeaderUI.java の中に次のような部分が 2 箇所あります。

コード:
    TableCellRenderer renderer = aColumn.getHeaderRenderer();



この部分を次のように書き換えれば、実行できます。

コード:
    TableCellRenderer renderer = aColumn.getHeaderRenderer();
    if (renderer == null) {
	renderer = header.getDefaultRenderer(); 
    }






かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2003-10-08 16:59
引用:

このページが参考になると思います。
http://www2.gol.com/users/tame/swing/examples/JTableExamples1.html



嗚呼、このサイトのことを知っていれば、clickableなtable headerの実装に悩まずにすんだのに。
# 出来あがったものは、似たようなものだけど
hira
会議室デビュー日: 2003/10/07
投稿数: 6
投稿日時: 2003-10-09 09:09
さくらばさん、ご返信頂き大変ありがとうございます。

教えていただいたサイトですが、サンプルが豊富にありますね。
大変勉強になります、ありがとうございます。

実行も、ご指摘の部分の変更で無事実行できました。
サイズが多少ずれるという問題もありましたが、ColumnMarginを
調節する事でうまくいきました。

ちなみに、JTable Examples 7のMultiple Row Header サンプルですが、
これがどうしてもうまく実行できません。
現在調査中ですが、もしご存知であればご指摘頂ければ幸いです。

かずくんさんのおっしゃる通り、もっと早く知っていればと思いましたf^_^;
後はがんばって理解できるようになる事ですね。
本当にありがとうございます。

スキルアップ/キャリアアップ(JOB@IT)