更新や削除など既存レコードの操作を行うには、どのレコードを対象にするのか明確にしなければなりません。具体的には画面上でレコードを選択できるようにします。
Javaの Swing には JTable などデータを表のように表示し、選択できる便利なクラスがありますが、少し設定が難しいので、今回は JList クラスを使った簡単な例で解説します。まずはリストの項目で選択したデータを取り出せるようにします。
また最終的な仕上げに向けて、ボタンやメニューを整理しました。都道府県のデータもウィンドウを表示した時点ですぐに表示するようにしています。
【1】sample213 フォルダをフォルダごとコピーして、sample214 フォルダを作ります。

【2】今回は以下のようなファイル構成になりますので、コピーした余計なものは削除してください。

*SampleDb030.class を忘れないようにしてください。
【3】PrefTest.java を以下のように変更します。
*「\」はWindowsではエンマークのことです。
保存先 C:\java\sample214
ファイル名 PrefTest.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.sql.*;
import java.util.*;
class PrefFrame extends JFrame implements ActionListener, ListSelectionListener {
Container cp;
JLabel lb1;
JList lt;
JButton btn1, btn2, btn3, btn4;
JMenuItem mi1, mi2, mi3, mi4, mi5, mi6;
public PrefFrame(String title) {
//フレームのタイトル
setTitle(title);
//コンテンツペイン取得
cp = getContentPane();
//ウィンドウを閉じる時
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
showExitDialog();
}
});
//Look&Feelの設定
/*
String type = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
try {
UIManager.setLookAndFeel(type);
} catch ( Exception e ) {
System.out.println("例外発生:" + e );
}
*/
//メニューバーの生成
JMenuBar mb = new JMenuBar();
//メニューの生成
JMenu mn1 = new JMenu("ファイル");
JMenu mn2 = new JMenu("編集");
JMenu mn3 = new JMenu("検索");
//メニュー項目の生成
mi1 = new JMenuItem("追加");
mi2 = new JMenuItem("更新");
mi3 = new JMenuItem("削除");
mi4 = new JMenuItem("終了");
mi5 = new JMenuItem("検索");
mi6 = new JMenuItem("全件表示");
//イベントリスナーの登録
mi1.addActionListener(this);
mi2.addActionListener(this);
mi3.addActionListener(this);
mi4.addActionListener(this);
mi5.addActionListener(this);
mi6.addActionListener(this);
//メニューへの追加
mn1.addSeparator(); //セパレーター
mn1.add(mi4);
mn2.add(mi1);
mn2.add(mi2);
mn2.add(mi3);
mn3.add(mi5);
mn3.add(mi6);
//メニューバーへの追加
mb.add(mn1);
mb.add(mn2);
mb.add(mn3);
//メニューバーをフレームへ追加
setJMenuBar(mb);
//ラベル
lb1 = new JLabel("ボタンをクリックしてください。", SwingConstants.CENTER);
lb1.setOpaque(true);
lb1.setFont(new Font("Dialog", Font.PLAIN, 12));
lb1.setBackground(Color.WHITE);
lb1.setForeground(Color.BLUE);
cp.add(lb1, BorderLayout.NORTH);
//リスト
lt = new JList();
lt.setFont(new Font("Dialog", Font.PLAIN, 14));
lt.setForeground(new Color(64, 64, 64));
lt.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lt.addListSelectionListener(this);
JScrollPane sp = new JScrollPane(lt);
cp.add(sp, BorderLayout.CENTER);
//パネル
JPanel pn1 = new JPanel();
pn1.setLayout(new GridLayout(1, 4));
//ボタンの設定
btn1 = new JButton("追加");
btn2 = new JButton("更新");
btn3 = new JButton("削除");
btn4 = new JButton("終了");
btn4.setForeground(new Color(255, 0, 0));
btn1.addActionListener(this);
btn2.addActionListener(this);
btn3.addActionListener(this);
btn4.addActionListener(this);
pn1.add(btn1);
pn1.add(btn2);
pn1.add(btn3);
pn1.add(btn4);
//パネルを追加
cp.add(pn1, BorderLayout.SOUTH);
//データ表示
prefDisplay();
}
public void actionPerformed (ActionEvent e) {
Object obj = e.getSource();
if (obj == btn1 || obj == mi1) {
}else if (obj == btn2 || obj == mi2) {
}else if (obj == btn3 || obj == mi3) {
}else if (obj == btn4 || obj == mi4) {
showExitDialog();
}else if (obj == mi5) {
}else if (obj == mi6) {
}
}
public void valueChanged (ListSelectionEvent e) {
String str = (String)lt.getSelectedValue();
StringTokenizer st = new StringTokenizer(str, ",");
int arraySize = st.countTokens();
String[] tkn = new String[arraySize];
int i = 0;
while(st.hasMoreTokens()) {
tkn[i] = st.nextToken();
i++;
}
lb1.setText("PREF_CD:" + tkn[0] + " PREF_NAME:" + tkn[1]);
}
private void prefDisplay () {
try {
//データベースに接続
Connection con = SampleDb030.getConnection();
//ステートメントオブジェクトを作成
Statement stmt = con.createStatement();
//SQL文作成
String mySql = "select * from T01Prefecture order by PREF_CD";
//検索するSQL実行
ResultSet rs = stmt.executeQuery(mySql);
ArrayList<String> listData = new ArrayList<String>();
//結果セットからデータを取り出す next()で次の行に移動
while(rs.next()) {
int prefCd = rs.getInt("PREF_CD");
String prefName = rs.getString("PREF_NAME");
listData.add(prefCd + "," + prefName);
}
lt.setListData(listData.toArray());
//オブジェクトを解放
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
System.out.println("例外発生:" + e );
}
}
private void showExitDialog () {
//終了ダイアログボックスの表示
int ret = JOptionPane.showConfirmDialog (cp, "プログラムを終了しますか?", "確認", JOptionPane.YES_NO_OPTION);
if(ret == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
}
public class PrefTest {
public static void main(String args[]) {
PrefFrame frm = new PrefFrame("都道府県マスター");
//フレームの設定
frm.setLocation(300, 200);
frm.setSize(250, 350);
frm.cp.setBackground(Color.LIGHT_GRAY);
frm.setVisible(true);
}
}
【4】コマンドプロンプトを起動して、カレントディレクトリを sample214 に切り替えます。

【5】javac PrefTest.java と入力し、コンパイルします。

【6】java PrefTest と入力し、プログラムを実行します。

【7】都道府県マスターが表示されました。これまでとはボタンが変わっています。「終了」以外のボタンはまだ動きません。

【8】都道府県のリストから「東京都」をクリックします。

【9】上のラベルに、選択した都道府県のデータが表示されることを確認してください。

【10】他の都道府県もクリックして試してください。

【11】メニュー項目やボタンの「終了」が正しく動作することを確認してください。
【解説】
(1)インポート部分
AWTだけでは足りないイベントを扱うので、「javax.swing.event.*;」を追加しました。また StringTokenizer クラスと ArrayList クラスを使うため「java.util.*;」も追加しました。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.sql.*;
import java.util.*;
(2)リストの項目を選択した時のイベント処理を行うため、ListSelectionListener インターフェイスを実装しました。
class PrefFrame extends JFrame implements ActionListener, ListSelectionListener {
(3)Look&Feelの部分はコメントにしています。今後は好みで設定してください。何も設定しなければ、Swingでは「Metal」がデフォルトです。
type に指定できる文字列
・Windows タイプ
com.sun.java.swing.plaf.windows.WindowsLookAndFeel
・Metal タイプ(Javaの標準)
javax.swing.plaf.metal.MetalLookAndFeel
・UNIX タイプ
com.sun.java.swing.plaf.motif.MotifLookAndFeel
・Motif タイプ(すべてで使える)
com.sun.java.swing.plaf.motif.MotifLookAndFeel
(4)ボタンやメニュー項目を整理して、少し書き直しました。
表示、リセットは省き、全件表示を加えています。
(5)都道府県を表示するコンポーネントを、テキストエリア(JTextArea)からリスト(JList)に変更しました。
lt = new JList();
lt.setFont(new Font("Dialog", Font.PLAIN, 14));
lt.setForeground(new Color(64, 64, 64));
・ListSelectionModel.SINGLE_SELECTION でリストの項目が1つしか選択できないようにしています。
lt.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
・リストにイベントリスナーを登録しています。
lt.addListSelectionListener(this);
・JListにはスクロールする機能がないので、JScrollPaneクラスのインスタンスに加えることで、スクロールバーを表示しています。そしてコンテンツペイン(cp)にはスクロールペイン(sp)の方を加えます。
JScrollPane sp = new JScrollPane(lt);
cp.add(sp, BorderLayout.CENTER);
(6)actionPerformed()メソッドについて
「終了」以外はまだ何も設定していませんので、ボタンをクリックしても何も起こりません。
public void actionPerformed (ActionEvent e) {
Object obj = e.getSource();
if (obj == btn1 || obj == mi1) {
}else if (obj == btn2 || obj == mi2) {
}else if (obj == btn3 || obj == mi3) {
}else if (obj == btn4 || obj == mi4) {
showExitDialog();
}else if (obj == mi5) {
}else if (obj == mi6) {
}
}
(7)valueChanged()メソッドについて
このメソッドはリストの項目をクリックした時に呼び出されるイベントハンドラです。
・リストで選択した項目の値を取得しています。
String str = (String)lt.getSelectedValue();
Java の API 仕様で JList クラスの getSelectedValue() メソッドを調べると、このメソッドは Object 型の戻り値を返すことがわかります。
public Object getSelectedValue()
そこで型を一致させるため、キャスト演算子で String 型に変換する必要があります。
または .toString() メソッドで String 型に変換する方法もあります。
String str = lt.getSelectedValue().toString();
分けて書いたほうが理解しやすいかもしれませんね。
Object obj = lt.getSelectedValue();
String str = obj.toString();
・StringTokenizerクラスは文字列を指定文字で区切るときに使用します。2番目の引数の指定文字列は何でもOKです。標準では空白文字で区切ります。
StringTokenizer st = new StringTokenizer(str, ",");
・取り出した文字列を格納する配列の準備です。取り出す文字列数を配列の要素数にしています。
int arraySize = st.countTokens();
String[] tkn = new String[arraySize];
・コンストラクタで引数にした、指定文字「,」カンマで区切って取り出しています。
int i = 0;
while(st.hasMoreTokens()) {
tkn[i] = st.nextToken();
i++;
}
今回は2つしかないことがわかっていますので、while を使うまでもないのですが、データベースの列数が増えてきたときの練習です。
・ラベルに表示しています。
lb1.setText("PREF_CD:" + tkn[0] + " PREF_NAME:" + tkn[1]);
*これで都道府県リストの項目をクリックした時に、参照型変数の tkn に値が代入される仕組みができました。変数をメソッドの外で宣言することで、他のメソッドからも利用できます。これを更新、削除の時に利用します。
(8)prefDisplay()メソッドについて
リストの項目を設定するには、 JList クラスの setListData() メソッドを使い、引数にObject型の配列を指定する必要があります。
引数に String クラスの配列を指定することもできますが、データベースのレコード数は増減しますので、配列の要素数が未定です。
String[] listData = new String[ ? ];
データベースから現在のレコード数を取り出し、配列の要素数とする方法もありますが、今回は ArrayList クラスを使ってみます。ArrayListクラスはサイズを変更できる配列を扱えます。
・<String>はこの配列はString型用として使うことを意味します。
ArrayList<String> listData = new ArrayList<String>();
・データを文字列として加えている部分です。この「,」カンマがデータを取り出す時に指定文字にしているので重要です。
listData.add(prefCd + "," + prefName);
・JList の引数はObject型の配列にしなければならないので、 ArrayList クラスの toArray() メソッドでObject型の配列を返しています。
lt.setListData(listData.toArray());
(9)コンストラクタの最後で prefDisplay() メソッドを呼び出していますので、ウィンドウが表示されたらすぐにデータが表示されます。
public PrefFrame(String title) {
省略
prefDisplay();
}