Javaにもメニューバーを表示するためのクラスが用意されているので、簡単にメニュー機能を加えることができます。そこでボタンをクリックした時と同じ動作を、メニューバーからも実行できるように改良してみましょう。
今回はメニューバーを作る練習が目的ですので、メニューは適当です。「編集」や「検索」のメニューは表示しているだけで動きませんのでご了承ください。
またメニューバーの作り方に専念していただきたいので、配列を使ったほうが簡潔に書ける部分でもあえて使っていません。
【1】sample207 フォルダをフォルダごとコピーして、sample208 フォルダを作ります。
【2】今回は以下のようなファイル構成になりますので、コピーした余計なものは削除してください。
*SampleDb030.class を忘れないようにしてください。
【3】PrefTest.java を以下のように変更します。
*「\」はWindowsではエンマークのことです。
保存先 C:\java\sample208
ファイル名 PrefTest.java
import java.awt.*;
import java.awt.event.*;
import java.sql.*;
class PrefFrame extends Frame implements ActionListener {
Label lb1;
TextArea txtar1;
Button btn1, btn2, btn3;
ExitDialog dlog;
MenuItem mi1, mi2, mi3, mi4, mi5, mi6,mi7;
public PrefFrame(String title) {
//フレームのタイトル
setTitle(title);
//ウィンドウを閉じる時
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dlog.setVisible(true);
}
});
//メニューバーの生成
MenuBar mb = new MenuBar();
//メニューの生成
Menu mn1 = new Menu("ファイル");
Menu mn2 = new Menu("編集");
Menu mn3 = new Menu("検索");
//メニュー項目の生成
mi1 = new MenuItem("表示");
mi2 = new MenuItem("クリア");
mi3 = new MenuItem("終了");
mi4 = new MenuItem("追加");
mi5 = new MenuItem("更新");
mi6 = new MenuItem("削除");
mi7 = new MenuItem("検索");
//イベントリスナーの登録
mi1.addActionListener(this);
mi2.addActionListener(this);
mi3.addActionListener(this);
//メニューへの追加
mn1.add(mi1);
mn1.add(mi2);
mn1.addSeparator(); //セパレーター
mn1.add(mi3);
mn2.add(mi4);
mn2.add(mi5);
mn2.add(mi6);
mn3.add(mi7);
//メニューバーへの追加
mb.add(mn1);
mb.add(mn2);
mb.add(mn3);
//メニューバーをフレームへ追加
setMenuBar(mb);
//ラベル
lb1 = new Label("ボタンをクリックしてください。", Label.CENTER);
lb1.setFont(new Font("Serif", Font.BOLD, 12));
lb1.setBackground(Color.WHITE);
lb1.setForeground(Color.BLUE);
add(lb1, BorderLayout.NORTH);
//テキストエリア
txtar1 = new TextArea();
txtar1.setFont(new Font("Dialog", Font.PLAIN, 14));
txtar1.setForeground(new Color(64, 64, 64));
add(txtar1, BorderLayout.CENTER);
//パネル
Panel pn1 = new Panel();
pn1.setLayout(new GridLayout(1, 3));
//ボタンの設定
btn1 = new Button("表示");
btn2 = new Button("クリア");
btn3 = new Button("終了");
btn3.setForeground(new Color(255, 0, 0));
btn1.addActionListener(this);
btn2.addActionListener(this);
btn3.addActionListener(this);
pn1.add(btn1);
pn1.add(btn2);
pn1.add(btn3);
//パネルを追加
add(pn1, BorderLayout.SOUTH);
//ダイアログボックス生成
dlog = new ExitDialog(this, "プログラムを終了しますか?");
}
public void actionPerformed (ActionEvent e) {
Object obj = e.getSource();
if (obj == btn1 || obj == mi1) {
prefDisplay();
lb1.setText("表示しました。");
}else if (obj == btn2 || obj == mi2) {
txtar1.setText("");
lb1.setText("クリアしました。");
}else if (obj == btn3 || obj == mi3) {
dlog.setVisible(true);
}
}
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);
StringBuffer temp = new StringBuffer();
//結果セットからデータを取り出す next()で次の行に移動
while(rs.next()) {
int prefCd = rs.getInt("PREF_CD");
String prefName = rs.getString("PREF_NAME");
temp.append(prefCd + "\t");
temp.append(prefName + "\n");
}
txtar1.setText(temp.toString());
//オブジェクトを解放
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
System.out.println("例外発生:" + e );
}
}
}
class ExitDialog extends Dialog implements ActionListener {
public ExitDialog(Frame parent, String title) {
//スーパークラスのコンストラクタを呼び出す
super(parent, title);
//ダイアログボックスを閉じる時
addWindowListener( new WindowAdapter () {
public void windowClosing(WindowEvent e) {
setVisible(false);
}
});
//ダイアログボックスの設定
setLocation(320, 300);
setSize(220, 80);
setLayout(new FlowLayout(FlowLayout.CENTER,10,10));
setBackground(Color.LIGHT_GRAY);
//ボタンの設定
Button btnYes = new Button("はい");
Button btnNo = new Button("いいえ");
Font f = new Font ("Dialog", Font.PLAIN, 14);
btnYes.setFont (f);
btnNo.setFont (f);
btnYes.setForeground(new Color(255, 0, 0));
btnYes.addActionListener(this);
btnNo.addActionListener(this);
add(btnYes);
add(btnNo);
}
public void actionPerformed(ActionEvent e) {
String str = e.getActionCommand();
if( str.equals("はい") ) {
System.exit(0);
} else if( str.equals("いいえ") ) {
setVisible(false);
}
}
}
public class PrefTest {
public static void main(String args[]) {
PrefFrame frm = new PrefFrame("都道府県マスター");
//フレームの設定
frm.setLocation(300, 200);
frm.setSize(250, 350);
frm.setBackground(Color.LIGHT_GRAY);
frm.setVisible(true);
}
}
【4】コマンドプロンプトを起動して、カレントディレクトリを sample208 に切り替えます。
【5】javac PrefTest.java と入力し、コンパイルします。
【6】java PrefTest と入力し、プログラムを実行します。
【7】ウィンドウが表示されました。新たにメニューバーが追加されています。
【8】メニューの「ファイル」をクリックします。
【9】メニュー項目が表示されました。
【10】ファイルのメニュー項目から「表示」を選択します。
【11】データが表示され、ラベルにメッセージが表示されました。
【12】ファイルのメニュー項目から「クリア」を選択します。
【13】データがクリアされ、ラベルのメッセージが変わりました。
【14】ファイルのメニュー項目から「終了」を選択します。
【15】確認のダイアログボックスが表示されました。
まだ続きがありますので、「いいえ」をクリックしてください。
【16】「編集」や「検索」メニューにもメニュー項目が表示されていますが、イベントリスナーの登録をしていないので、クリックしても何も起こりません。
【17】ボタンも通常通り動作することを確認してください。
【解説】
(1)ウィンドウにメニューバーを表示するには、MenuBarクラス、Menuクラス、MenuItemクラスを使います。それぞれの関係を以下の図に示します。
(2)MenuItem を Menu に加え、Menu を MenuBar に加え、最終的に MenuBar を Frame(ウィンドウ)に加えます。 Menu や MenuItem は複数作ることができます。
Frame ← MenuBar ← Menu ← MenuItem
プログラムで書くと、
mn1.add(mi1); メニュー項目をメニューへ追加
↓
mb.add(mn1); メニューをメニューバーへ追加
↓
setMenuBar(mb); メニューバーをフレームへ追加
(3)メニュー項目の間にセパレーターを入れることができます。
mn1.addSeparator();
(4)イベントオブジェクトが発生するのは MenuItem ですので、このコンポーネントにイベントリスナーを登録します。
mi1.addActionListener(this);
mi2.addActionListener(this);
mi3.addActionListener(this);
(5)ウィンドウのactionPerformed()メソッドについて
今回の重要な点は、「メニュー項目を選択した時」と「ボタンをクリックした時」は同じイベントオブジェクトが発生するので、同じイベントハンドラで処理していることです。
e.getSource()でイベントソースが取得できますが、このメソッドの戻り値はObject型です。そこでObject型の参照型変数で受け取って以降の判定に利用しています。
Object obj = e.getSource();
if (obj == btn1 || obj == mi1) {
prefDisplay();
lb1.setText("表示しました。");
}else if (obj == btn2 || obj == mi2) {
txtar1.setText("");
lb1.setText("クリアしました。");
}else if (obj == btn3 || obj == mi3) {
dlog.setVisible(true);
}
*「||」は論理演算子です。メニュー項目かボタンのどちらか一方がイベントソースなら条件式は満たされます。
*参照型変数を使わない場合は以下のように長くなります。
if (e.getSource() == btn1 || e.getSource() == mi1) {
(6)MenuItem は コンストラクタ内で使うだけでなく、actionPerformed()メソッドでも参照するので、メソッドの外で宣言しています。(配列にすることもできます)
MenuItem mi1, mi2, mi3, mi4, mi5, mi6,mi7;
(7)メニューバーが目立つようにラベルの背景色は白に変更しました。
lb1.setBackground(Color.WHITE);
【ワンポイント】
終了確認のためのダイアログボックスを表示しているクラスは、前回と変わらないのでコンパイル済みのクラスファイルを使うこともできます。
クラスファイルを使うとソースファイルからダイアログボックスの部分を省略できますので、プログラムがシンプルになります。
クラスファイルを使う場合は、以下の2つをコピーしてソースコードと同じ場所に配置します。
ExitDialog.class
ExitDialog$1.class
ダイアログボックスを閉じる時の処理に、無名内部クラスを使っていますので、コンパイルするとクラスファイルは2つになります。
余裕がある方は試してみると理解が深まりますよ。