学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Javaプログラミング入門その46 JTableを利用したプログラム

>>この記事には書き直した新しいページがあります。<<


<<前  [TOP]  次>>


データを行と列の形式で表示・操作するには、「テーブル」を使うのが便利です。
テーブルは、「テーブルヘッダ」「列」「セルの値」から構成されています。
テーブルを生成する際に使用するコンポーネントはjavax.swing.JTableですが、JTableを処理するためのクラスとインターフェイスは、javax.swing.tableパッケージになります。
tableパッケージには、テーブルのモデルや、列やヘッダーの管理といったことが定義されています。

java.lang.Object
    +--java.awt.Component
        +--java.awt.Container
            +--javax.swing.JComponent
                +--javax.swing.JTable



JTableで生成されるテーブルは「列」が基本となりますが、「行」においても選択などの操作をプログラムで記述するのは用意です。
また、列・行とも始まりは「0」からとなります。


以下のようにテーブルを生成すると、10行×5列のテーブルが生成されます。

JTable tree = new JTable(10, 5);    // 10行×5行のテーブル



先に生成されたテーブルは、列を表す「テーブルヘッダ」を持ちません。
ヘッダを持たせるためにはテーブルをスクロールペインに配置する必要があります。

JTable table = new JTable(10, 5);    //10行×5列のテーブル
JScrollPane sp = new JScrollPane(table);    // スクロールペインに配置

これで、1列目に「A」、2列目に「B」というように、テーブルヘッダが付加されます。
テーブルヘッダを持つことで、列の入れ替えや、列幅の変更などが可能になります。
なお、列幅の操作は「setAutoResizeMode(定数)」を用います。
定数は「AUTO_RESIZE_SUBSEQUENT_COLUMNS」です。


テーブルヘッダをより分かりやすくするために自分なりの名称にする場合は、テーブルモデルを作成する必要があります。


テーブルモデルは、javax.swing.tableパッケージにあります。
テーブルモデルの大本はTableModelインターフェイスで、AbstractTableModelという抽象クラスがTableModelインターフェイスのメソッドを実装していますので、自分なりにテーブルモデルを使用する場合には、AbstractTableModelを継承したクラスを作成すればよいです。


テーブルモデルを使用するので、tableパッケージをインポートする必要があります。

import javax.swing.table.*;   //テーブルモデルを定義するために必要です

//headerで定義したヘッダを元に5行のテーブルモデルを生成
String[] header = { "国語", "数学", "合計"};
DefaultTableModel model = new DefaultTableModel(header, 5);
JTable table = new JTable(model);

テーブルの情報を指定して、5行のDefaultTableModelを生成し、そのテーブルモデルを基にJTableを生成します。


テーブル内で変更があった場合に処理するには、javax.swing.eventにあるTableModelListenerインターフェイスを利用するのが便利です。
対応するメソッドは、tableChanged(TableModelEvent e)で、これにより変更された列・行・セルを知ることが出来ます。

import javax.swing.event.*;

 public class JTableTest implements TableModelListener {

    DefaultTableModel model;
        :
     model.addTableModelListener(this);    //modelをイベント処理

     /** テーブルに編集が加えられたときの処理 */
    public void tableChanged(TableModelEvent e) {
        :



このとき、列などの情報は以下のようなメソッドで取得します。
TableChangedに渡されるTableModelEventが「e」だとします。

int e.getColumn()変更された列を取得
int e.getFirstRow()変更された最初の行を取得
int e.getLastRow()変更された最後の行を取得
int e.getType()イベントのタイプを取得(INSERT, UPDATE, DELETE)


上記はイベントが発生した場所を取得していますが、JTableでは現在選択されている場所を取得することも可能です。
例えば、getSelectedRow()メソッドは「選択されている行を取得」します。


また、各セルの内容は、DefaultTableModelあるいはJTableの「getValueAt(行, 列)」で取得し、設定は「setValueAt(object), 行, 列)」で行います。
いずれも、DefaultTableModelのメソッドで使用した場合はテーブルモデルで生成された列が基準となり、JTableのメソッドで使用した場合は表示されている列が基準となります。
列の入れ替えを行った場合に、この差は決定的ですから注意が必要です。


行の追加・削除・移動を行う際には、テーブルモデルに対して以下のようなメソッドを使用します。
addRow(Object)最後に行を追加
insertRow(int, Object)intで指定された行に挿入
moveRow(int, int, int)第1〜2引数で指定された行を第3引数の場所へ移動
removeRow(int)指定された行を削除
列の追加・削除・移動は、tableパッケージのTableColumnクラスを利用することにより可能になります。


以下のサンプルプログラムを作成して、実行してみましょう。


【SwingJTableTest1.java】

/** JTableのテスト{スクロールペイン無し} */

import javax.swing.*;

public class SwingJTableTest1 {

	private JTable table;

	/** コンストラクタ*/
	public SwingJTableTest1() {
		table = new JTable(10, 5);	//10行*5列のJTableの生成
	}

	/**main()*/
	public static void main(String[] args) {
		SwingJTableTest1 sample = new SwingJTableTest1();

		JFrame frame = new JFrame("JTableTest1");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().add(sample.table, "Center");
		frame.pack();
		frame.setVisible(true);
	}
}



実行すると、10行*5列のテーブルが表示されます。








以下のサンプルプログラムを作成して、実行してみましょう。


【SwingJTableTest2.java】

/** JTableのテスト{スクロールペイン有り} */
import javax.swing.*;

public class SwingJTableTest2 {
	private JTable table;
	private JScrollPane sp;

	/** コンストラクタ*/
	public SwingJTableTest2() {
		table = new JTable(10, 5);	//10行*5列のJTableの生成
		sp = new JScrollPane(table);	//スクロールペインに付加
	}

	/**main()*/
	public static void main(String[] args) {
		SwingJTableTest2 sample = new SwingJTableTest2();

		JFrame frame = new JFrame("JTableTest2");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().add(sample.sp, "Center");
		frame.pack();
		frame.setVisible(true);
	}
}



実行すると、テーブルが表示され、列先頭のヘッダ(A〜E)をドラッグすることで列の入れ替えや、列幅の変更などができます。








以下のサンプルプログラムを作成して、実行してみましょう。


【SwingJTableTest3.java】

/** JTableのテスト{テーブルヘッダを任意のものにする} */

import javax.swing.*;
import javax.swing.table.*;	//テーブルモデルを定義するために必要

public class SwingJTableTest3 {

	private JTable table;
	private JScrollPane sp;
	private DefaultTableModel model;

	/** コンストラクタ*/
	public SwingJTableTest3() {

		//headerで定義したヘッダを元に5行のテーブルモデルを生成
		String[] header = { "Japanese", "Math", "Sum" };
		model = new DefaultTableModel(header, 5);

		table = new JTable(model);	
		sp = new JScrollPane(table);	
	}

	/**main()*/
	public static void main(String[] args) {
		SwingJTableTest3 sample = new SwingJTableTest3();

		JFrame frame = new JFrame("JTableTest3");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().add(sample.sp, "Center");
		frame.pack();
		frame.setVisible(true);
	}
}



実行すると、テーブルが表示されます。
テーブルヘッダに任意の名前が付いています。








以下のサンプルプログラムを作成して、実行してみましょう。


【SwingJTableTest4.java】

/** JTableのテスト{1列目+2列目の計算結果を3列目に表示} */

import javax.swing.*;
import javax.swing.table.*;	//テーブルモデルを定義するために必要
import javax.swing.event.*;	//TableModelEventを利用するために必要

public class SwingJTableTest4 implements TableModelListener {

	private JTable table;
	private JScrollPane sp;
	private DefaultTableModel model;

	/**  コンストラクタ */
	public SwingJTableTest4() {

		// headerで定義したヘッダを元に5行のテーブルモデルを生成
		String[] header = { "Japanese", "Math", "Sum" };
		model = new DefaultTableModel(header, 5);

		table = new JTable(model);	
		sp = new JScrollPane(table);

		model.addTableModelListener(this);	// modelのイベント通知登録
	}

	/** テーブルに編集が加えられたときの処理 */
	public void tableChanged(TableModelEvent evt) {

		int a, b;
		int row = evt.getFirstRow();	// 選択されている(先頭)行を取得

		if ( evt.getColumn() == 2) {	// 3列目が編集されたら何もしない
			return;
		}

		// 1列目と2列目の内容を整数へ変換(不正な値は0とする)
		try {

			a = Integer.parseInt((String)model.getValueAt(row, 0));
		}
		catch(NumberFormatException nfex) {
			model.setValueAt("0", row, 0);
			a = 0;
		}

		try {

			b = Integer.parseInt((String)model.getValueAt(row, 1));
		}
		catch(NumberFormatException nfex) {
                        model.setValueAt("0", row, 1);
                        b = 0;
                }
	
		// 1〜2列目の計算結果を3列目に設定
		model.setValueAt(new Integer(a+b), row, 2);
	}


	/** main() */
	public static void main(String[] args) {
		SwingJTableTest4 sample = new SwingJTableTest4();

		JFrame frame = new JFrame("JTableTest4");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().add(sample.sp, "Center");
		frame.pack();
		frame.setVisible(true);
	}
}



実行するとテーブルが表示され、1列目+2列目の計算結果が3列目に表示されます。


**注意**
TableModelEventは将来のSwingリリースと互換性がなくなるため、現在、コンパイルには-Xlint:deprecationオプションが必要になっています。
さらにInteger(int)の記述が推奨されないという警告が出ます。









以下のサンプルプログラムを作成して、実行してみましょう。


【SwingJTableTest5.java】

/** JTableのテスト{行の挿入/削除/移動} */

import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;	//テーブルモデルを定義するために必要
import javax.swing.event.*;	//TableModelEventを利用するために必要

public class SwingJTableTest5 implements ActionListener, TableModelListener {

	private JTable table;
	private JScrollPane sp;
	private DefaultTableModel model;
	private JMenuBar menuBar;

	/**  コンストラクタ */
	public SwingJTableTest5() {

		// メニュー設定
		menuBar = new JMenuBar();
		JMenu editMenu = new JMenu("Edit");
		JMenuItem insertItem = new JMenuItem("Insert");
		JMenuItem removeItem = new JMenuItem("Delete");
		JMenuItem moveItem = new JMenuItem("Move");
		editMenu.add(insertItem);
		editMenu.add(removeItem);
		editMenu.add(moveItem);
		menuBar.add(editMenu);

		// headerで定義したヘッダを元に5行のテーブルモデルを生成
		String[] header = { "Japanese", "Math", "Sum" };
		model = new DefaultTableModel(header, 5);

		table = new JTable(model);	
		sp = new JScrollPane(table);

		model.addTableModelListener(this);	// modelのイベント通知登録

		// メニューのイベント通知登録
		insertItem.addActionListener(this);
		removeItem.addActionListener(this);
		moveItem.addActionListener(this);
	}
	

	/** テーブルに編集が加えられたときの処理 */
	public void tableChanged(TableModelEvent evt) {

		int a, b;
		int row = evt.getFirstRow();	// 選択されている(先頭)行を取得

		if ( evt.getColumn() == 2) {	// 3列目が編集されたら何もしない
			return;
		}

		// 「削除」のときは何もしない(最終行を削除したときにエラーになるため)
		if(evt.getType() == TableModelEvent.DELETE) {
			return;
		}

		// 1列目と2列目の内容を整数へ変換(不正な値は0とする)
		try {

			a = Integer.parseInt((String)model.getValueAt(row, 0));
		}
		catch(NumberFormatException nfex) {
			model.setValueAt("0", row, 0);
			a = 0;
		}

		try {

			b = Integer.parseInt((String)model.getValueAt(row, 1));
		}
		catch(NumberFormatException nfex) {
                        model.setValueAt("0", row, 1);
                        b = 0;
                }
	
		// 1〜2列目の計算結果を3列目に設定
		model.setValueAt(new Integer(a+b), row, 2);
	}


	/** メニュー選択時の処理 */
	public void actionPerformed(ActionEvent evt) {
		String command = evt.getActionCommand();

		Object[] data = { "", "", "" };	// 「挿入」時の仮データ
		int row = table.getSelectedRow();	// 選択されている行を取得

		if (command.equals("Insert")) {
			model.insertRow(row+1, data);	//選択行の下に行追加
		}
		else if(command.equals("Delete")) {

			try {
				model.removeRow(row);	//選択行を削除
			}
			catch (ArrayIndexOutOfBoundsException e) {
				System.err.println("削除行を選択してください");
			}
		}
		else if(command.equals("Move")) {
			model.moveRow(row, row, 0);	// 選択行を1行目へ移動
		}
	}


	/** main() */
	public static void main(String[] args) {
		SwingJTableTest5 sample = new SwingJTableTest5();

		JFrame frame = new JFrame("JTableTest5");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().add(sample.sp, "Center");
		frame.setJMenuBar(sample.menuBar);	// メニューバーの追加
		frame.pack();
		frame.setVisible(true);
	}
}



実行するとテーブルが表示されます。
Editメニューから行の追加・削除・移動ができます。


**注意**
TableModelEventは将来のSwingリリースと互換性がなくなるため、現在、コンパイルには-Xlint:deprecationオプションが必要になっています。
さらにInteger(int)の記述が推奨されないという警告が出ます。









<<前  [TOP]  次>>