Java入門 ウィンドウアプリ編









Java入門
ウィンドウアプリ編

















この教科書はBookletを利用して作成している。

目 次

第二部 ウィンドウアプリの開発
 8章 最初のウィンドウアプリ
 9章 基本部品1
10章 基本部品2
11章 コマンドによる部品追加
12章 簡易エディタ
13章 ファイル入出力
14章 簡易エディタの拡張

第一部 Javaの文法
 0章 はじめに
 1章 最初のJavaプログラム
 2章 値の種類と式
 3章 入力と例外処理
 4章 条件分岐
 5章 繰り返し
 6章 配列
 7章 クラス・オブジェクト

Ⓐ を付けた項目は、時間の関係で面接授業では扱わない発展的内容なので、自学自習する際の参考にして欲しい。

参考:超入門
    1.準備
    2.外観の設計
    3.動作の記述

本書の見方
ページをめくる
左(右)矢印キーを押す
1ページ分の移動
左右上端にある[Next]、[Previous]タブをクリックする
章の頭に移動
右上の[章の移動]タブをクリックし、現れた章を選ぶ
ページのジャンプ
右上のページ番号表示タブをクリックし、現れたページを選ぶ
画像の拡大およびリンク先への移動
画像やリンク先をクリックすれば、別ウィンドウ(タブ)で表示される

第8章 最初のウインドウアプリ

本章では、NetBeansによる簡単なWindowsアプリケーション作成を通して、クラスとオブジェクトの概念がどのように活用されているかを学ぶ。また、Windowsアプリケーションのキーとなるイベント駆動の考え方についても学習する。そのため、NetBeans上での操作と、それに伴いNetBeansが(自動)生成するプログラムコードとを対比させて学習しよう。

8.0.クラスとオブジェクト

 JAVAでのアプリケーション開発にはオブジェクト指向プログラミングの基本概念であるオブジェクトやクラスの理解が欠かせない。説明を避けてきたが、実はこれまでもクラスやオブジェクトを陰に陽に利用してきている。本章ではウィンドウアプリの開発を通して学んでいこう。
 オブジェクト指向では、アプリケーション(システム)の基本構成要素は状態機能とを持つオブジェクト(個体)であると考える。オブジェクトの状態とは、そのオブジェクトの属性の値であり、機能とはそのオブジェクトが受け取れるメッセージ(命令)、あるいはそのオブジェクトが実行できるメソッド(関数)である。しかし、オブジェクトがどのような属性とメソッドを持つかは、オブジェクトの種類(、タイプ)によって異なる。オブジェクトの型を規定したものをクラスという。

8.1.ウィンドウズアプリケーション

 ウィンドウアプリケーションを作成する際は、標準のフレームクラス(JFrame)を目的に応じて拡張(属性やメソッドを追加・上書き)したクラスを定義し、その個体(オブジェクト)を生成・起動するという手順をとる。以下のその過程を、NetBeans上の操作とそれが生成するプログラムとを対比させながら、順を追って見てゆこう。

ステップ1.JFrameの利用
NetBeansを起動し、プロジェクトを開くか新規作成したら、新規ファイルで、SwingGUIフォーム→JFrameフォームを選択しクラス名を設定する(0.3.NetBeansの使い方)。現れたFrame上で右ボタンクリックをし「レイアウトを設定」で標準の「境界線レイアウト(BorderLayout)」を選ぶと次のプログラムができる。
 さらに、NetBeansで[ファイルを実行]を選べば、このプログラムが翻訳・実行され、最小化[_]、最大化[□]、閉じる[×]ボタンを備えた空ウィンドウが出現する。
public class A extends javax.swing.JFrame {
    public A() { initComponents(); }//コンストラクタ
    // 【Generated Code】                          

private void initComponents() {//閉じる[×]ボタンで終了 setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); pack();//最小サイズに }

public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() {new A().setVisible(true);}}); } }
ここで、背景が灰色の部分は編集できない(してはいけない)ことに注意

 例示のウィンドウズアプリケーションは、フレームクラスを拡張(extends JFrame)したクラス A を定義し、そのオブジェクトをコンストラクタ A() を使って作成(new A())・起動(setVisible(true))して実現される。例では、拡張部分はないが、フレームクラスが持ついくつかの属性値を具体的に定めて(setDefaultCloseOperation(), pack())、オブジェクトを生成している。この結果クラス A のオブジェクト(すなわち作成アプリケーション)は フレームクラス が持つ多くの機能を(改めてプログラムすることなく)利用できている。なお、コンストラクタ名はクラス名と同じにする規約である。
 ここでは、プログラムをNetBeans上で自動生成しNetBeansのシステム内で実行しているが、適当なエディタで同じものを作成し翻訳(javac)・実行(java)しても、同じ結果(ウィンドウアプリ)が現れることに注意しよう。逆に言えば、エディタを使ってプログラムを作成する手間を、NetBeansが大幅に端折ってくれる。
ステップ2.部品(オブジェクト)の配置とプロパティ(属性)設定
 次に、フレームにラベルを配置する拡張を以下の手順で行おう。
  1. パレットからラベル(JLabel)を選択し、フレーム(JFrame)に載せる
     jLabel1 という(変数)名のラベル(クラスJLabelのオブジェクト)が配置される
  2. jLabel1 の textプロパティを Hello! に設定する
その結果、緑字の4行が追加されて以下のプログラムができる。プログラムでは、JFrame に直接ではなく、ContentPane を取得して、その中に jLabel1 を配置するという手順を踏んでいることに注意しよう。配置方法はレイアウト属性と呼ばれ、BorderLayout、GridLayout、等があり、BorderLayoutでは、中央(CENTER)と上(PAGE_START)下(PAGE_END)左(LINE_START)右(LINE_END)に部品を配置できる。

public class A extends javax.swing.JFrame {
  public A() { initComponents(); }

private void initComponents() { jLabel1 = new javax.swing.JLabel();//オブジェクトjLabel1を生成し setDefaultCloseOperation(…); jLabel1.setText("Hello!");//テキストプロパティを「Hello!」にし //フレームの中央に置く getContentPane().add(jLabel1,java.awt.BorderLayout.CENTER); pack(); }

public static void main(String args[]) {…} //JLabelクラスのオブジェクトjLabel1をprivateで宣言

private javax.swing.JLabel jLabel1;

}
ステップ3.イベント駆動
 ラベルに加えてボタン(JButton)を配置し、ボタンをクリックするとラベル表示を変える機能を追加しよう。
  1. パレットからボタン(JButton)を選択し、フレーム上に配置する
  2. 配置した jButton1 のイベントでactionPerformedを選び、▼をクリックするとデザイン(エディタ)がソース(エディタ)に切り替わり

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){

        // TODO add your handling code here:

    }

    というイベントハンドラ(メソッド)の枠組みが現れるので

        // TODO add your handling code here:

    の位置に、次のように記述する

        jLabel1.setText("Clicked!");

    (jLabel1のtextプロパティを「Clicked!」に設定せよという意味)
この結果コードは緑と青の部分が追加されて以下のようになる。

public class A extends javax.swing.JFrame {
 public A() { initComponents(); }

private void initComponents() { jLabel1 = new javax.swing.JLabel(); jButton1 = new javax.swing.JButton(); setDefaultCloseOperation(…); jLabel1.setText("Hello!"); getContentPane().add(jLabel1,java.awt.BorderLayout.CENTER); jButton1.setText("jButton1"); jButton1.addActionListener(new java.awt.event.ActionListener(){ public void actionPerformed(java.awt.event.ActionEvent evt){ jButton1ActionPerformed(evt);} }); getContentPane().add(jButton1,java.awt.BorderLayout.PAGE_START); pack(); }

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){

jLabel1.setText("Clicked!");

}

public static void main(String args[]) {…}

private javax.swing.JButton jButton1; private javax.swing.JLabel jLabel1;

}
 ここで、イベント駆動について理解しよう。ウィンドウアプリケーションでは、動作中に生じる事象を一般にイベントと呼び、イベントに対する応答を記述する形でプログラムする。Javaでは、例えばボタンに、クリックのような標準ユーザ操作によって生じるイベント(ActionEvent)が起こると、対応する応答器(ActionListener)に備わる応答メソッド(actionPerformed())が実行されることになっている。例示プログラムではボタンjButton1に、応答メソッドをフレームのイベントハンドラjButton1ActionPerformed()の実行命令で上書きした応答器を追加し、そちらにボタンがクリックされときの応答を記述している。
 NetBeansのイベント欄からも分かるように、イベントには多くの種類があり、対応する応答器や応答メソッドにも多くの種類がある。

 ここまでそれなりに長いプログラムができたが、我々が入力したのはjLabel1.setText("Clicked!");の1文だけで、他はすべてNetBeansが我々の操作に応じて自動生成したことに注意しよう。そのおかげで我々は、アプリ開発にまつわる細部に関わることなく、プログラムの本質的な部分に専念できる。なお参考のため、この例題で作成したアプリを11章で説明するように、NetBeansを使わずプログラムを記述した例をこちらに置いておく。
 また、イベントハンドラを記述するときは必ずNetBeansのデザインエディタから部品とイベントを選んで、ハンドラ(の枠組み)を自動生成させなければならない。単にイベントハンドラ部分を記述しただけでは、上で解説したイベントの応答器(Listener)が生成されないので、正しく動かない。

実習.以下の手順で示されたアプリを作成しよう
1.この節で作成したフレームの下部にラベルを、中段の左、中央、右にボタンを配置する
2.ボタンのtextプロパティをそれぞれ、「開始」、「停止」、「終了」とする
3.開始(停止)ボタンがクリックされたら、ラベルに「開始(停止)ボタンが押されました」と表示させる
4.終了ボタンがクリックされたら、アプリケーションを終了させる(System.exit(0)を呼び出す)
5.ボタン等の、背景色(background)や文字色(foreground)、フォント(font)等のプロパティを適宜を設定し、initComponentsメソッド内にどのような命令文が追加されるか確認する

ここで作成するアプリはここからダウンロードできる。
ステップ4.変数名の変更
 NetBeansでは、作成するプログラム中の例えばボタンやラベルの変数名、イベントハンドラ名は jButton1、jLabel1、jButton1ActionPerformed など自動的につく。簡単なうちはそれでもよいが、複雑なプログラムではそれらの働きなどを表す分かりやすい名前に、次の手順で変えたほうがよい。
  • 変数名:対象を右クリック→変数名を変更…
  • イベントハンドラ名:イベント欄の[…]をクリック→名前の変更

ステップ5.起動ファイルの作成
 完成したウィンドウズプログラムは、NetBeansを開いたりせずに、ファイルを直接ダブルクリックすることで実行できないと不便である。ダブルクリックで単独起動可能なファイル(プロジェクト名.jar)は次の手順で作成する。
  1. プロジェクトを右クリックし、プロパティ→実行で、主クラスに目的のWindowsアプリケーションを指定する。
  2. メニュー→実行→主プロジェクトを削除して構築 を実行
  3. プロジェクトフォルダ内のdistフォルダに、プロジェクト名.jarファイルができる。

まとめ

本章で利用した部品とプロパティ、イベント、メソッドを以下の表にまとめている。自分の理解を確認しよう。

部品プロパティイベントメソッド
JButtontextactionPerformedString getText()
JLabeltext  --- void setText(String s)

課題

本章(8章)の実習プログラムを完成させよ。

第9章 Ⓐウィンドウズアプリの基本部品(1)

 ウィンドウアプリケーションでよく使われる基本的な部品として、ラジオボタンチェックボックスコンボボックスリストボックスの使用法について学ぶ。より詳しくはJavaのマニュアルページやインターネット情報、参考書等を見よ。 ここで作成するアプリはここからをダウンロードできる。

9.1.タブ付きページ

タブ付きペイン(JTabbedPane)上に必要な枚数のパネル(JPanel)を追加することで実現できる。

実習.タブ付きページとラベルの用意
次の手順でフレーム上にラベルとタブ付きページを用意しよう。
0)新規ファイルでSwingGUIフォーム→JFrameフォームを選び、適切なクラス名を指定する
1)JFrameのレイアウトを標準の境界線レイアウト(BorderLayout)に変更する
  JFrame上で右クリック→レイアウトを設定→境界線レイアウト
2)JFrameの下部にラベルを配置し、変数名とテキストを適宜設定する
  パネルを右クリックし、変数名を変更...
  パネルを右クリックし、テキストを編集
3)JFrameの中央にタブ付ペイン(JTabbedPane)を配置する
4)タブ付ペイン上に必要枚数のパネル(JPanel)を配置する
  配置したタブ付ペインを右クリック→パレットから追加→パネル
5)各パネルのタブタイトル、変数名を適宜変更する
  パネルを選択し、プロパティ→タブタイトル
  パネルを右クリックし、変数名を変更...
6)ページ(パネル)のレイアウトはフリーデザインのままでよい

注. NetBeansでタブ付きページを選択しているとき、タブ付きペイン(枠)を選択しているのか、パネル(ページ)を選択しているのか紛らわしいので注意せよ(左側のナビゲータ(インスペクタ)ウィンドウで確認できる)。

9.2.ラジオボタンとチェックボックス

 与えられた選択肢の中から選ばせるボタンツールにラジオボタンとチェックボックスがある。ラジオボタン(JRadioButton)はグループ化されたボタンの中から1個だけ選択させるもの(単数選択)で、それらを同一のボタングループ(ButtonGroup)に登録する必要がある。
 一方、チェックボックス(JCheckBox)は複数選択可能なので、ボタングループは必要ない。しかしイベントハンドラでは、どのチェックボックスが選択(解除)されたときでも同じ様に、複数のチェックボックスのそれぞれが選択されているか否かisSelected()メソッドを使って調べる必要がある。

実習.以下の手順でラジオボタンのページを完成させよう
1.ラジオボタンの配置とボタングループへの登録
1)9.1で準備したページ(例えば ラジオパネル)に、パレットからラジオボタン(JRadioButton) 3個を配置し、対象の右ボタンクリックから変数名とテキストを設定する。
2)ボタングループ(ButtonGroup)を配置する。ボタングループは非表示部品なので、ナビゲータ(インスペクタ)上の「他のコンポーネント」には表示されるが、デザインウィンドウ上には何も表示されないことに注意せよ。
3)各ラジオボタンのbuttonGroupプロパティを上で配置したボタングループに設定する。
4)ファイルを実行(Shift+F6)」し、ラジオボタンの単一選択機能が働いていることを確認する。

2.ラジオボタンのイベント処理
1)各ラジオボタンのactionPerformedイベントを選択し、現れるハンドラ内に
   (ラベル名).setText((ラジオボタン名).getText()+"を選択");;
と記述し、9.1で配置したラベルにラジオボタンのテキストを表示させる。
2)「ファイルを実行(Shift+F6)」し、正しく動いていることを確認する
プログラムチップス
  ラベル.setText(ラジオボタン.getText()+"を選択");
という文は、
  1. ラジオボタンのtextプロパティを取得(getText())し
  2. 文字列"を選択"をつなげて
  3. ラベルのtextプロパティに設定(setText())する
ことを意味する。このようにプロパティの読み書きには通常、取得メソッドgetProperty()と設定メソッドsetProperty()を利用する。

実習.以下の手順でチェックボックスのページを完成させよう
1.チェックボックスの配置
1)9.1で準備したパネル(例えば チェックパネル)に、パレットからチェックボックス(JCheckBox) 3個を配置し、適宜変数名とテキスト設定する

2. チェックボックスのイベント処理
1)1つのチェックボックスのactionPerformedイベントを選択し、現れるハンドラ内に
 String 文="";
 if ((チェックボックス1).isSelected()) 文+=(チェックボックス1).getText();
 if ((チェックボックス2).isSelected()) 文+=(チェックボックス2).getText();
 if ((チェックボックス3).isSelected()) 文+=(チェックボックス3).getText();
 (ラベル名).setText(文+"が選択されています");
と記述する。
2)1) で作成したイベントハンドラの名前を適宜修正する。
  イベント欄の[…]をクリック→名前の変更
3)他のチェックボックスのactionPerformedイベントに同じハンドラを設定する
  チェックボックスのactionPerformedイベント欄で[…]をクリック
 →現れたハンドラ設定ウィンドウで(必要なら[削除]し)[追加]ボタンをクリック
 →新しいハンドラ名を2)で設定したハンドラ名とする

プログラムチップス
 部品が選択されている否かを示すselectedプロパティの場合、値の取得メソッドはisSelected()、設定メソッドはsetSelected()である。特定のラジオボタンやチェックボックスをあらかじめ選択状態にしたいときは、NetBeansのselectedプロパティ欄で設定するか、コンストラクタ内の initComponennt(); 文の後で 部品名.setSelected(true); とする。

9.3.コンボボックスとリスト

 コンボボックスは、▼ボタンのクリックで現れる一覧の中から項目を選択させる部品である。リストは、コンボボックスと同様だが、最初から項目の一覧を(必要ならスクロール付きで)表示する。

実習.以下の手順でコンボボックスのページを作成せよ
1.コンボボックスの配置とmodel設定
1)作成した適当なパネルにJComboBoxを配置し変数名を適宜変更する
2)コンボボックスのmodelプロパティの[…]をクリックし、現れたウィンドウで項目リストを適宜編集する。
2.actionPerformedイベントハンドラを、例えば次のように記述する。
   (ラベル名).setText((コンボボックス名).getSelectedItem()
      +"が ComboBox で選択されました");

3.ファイルを実行(Shift+F6)」し、コンボボックスで選択した項目(item)が、ラベルに表示されることを確認する


プログラムチップス
 コンボボックスから取得した選択項目(getSelectedItem())は文字列ではない(オブジェクト型)ため、文字列をつなげるか、文字列に変換(getSelectedItem().toString())しないとエラーになる。

 リストにはactionPerformedイベントがないので、valueChangedイベントを利用する。また、選択項目を取得するメソッドがgetSselectedValue()(オブジェクト型)である点もコンボボックスとは異なる。

問.リストの追加
上の説明を参考に、コンボボックスのページにリスト(JList)を追加し、選択した項目がラベルに表示されるようにせよ。
注.NetBeansでJListを配置すると、自動的にJScrolPane(スクロールの枠)に載せた形で配置されるため、特に意識しなくても(必要に応じて)縦横のスクロールが表示される。確認せよ。

まとめ

本章で利用した部品とプロパティ、イベント、メソッドを以下の表にまとめている。自分の理解を確認しよう。

部品プロパティイベントメソッド
JRadioButtontextactionPerformedString getText()
JCheckBoxtextactionPerformedboolean isSelected(),
String getText()
JComboBoxmodelactionPerformedString (getSelectedItem()+"")
JListmodelvalueChangedString (getSelectedValue()+"")

課題

今回の例題および課題にしたがって、ラジオボタン、チェックボックス、コンボボックス、リストボックスを持つウィンドウズアプリケーションを作成せよ。

第10章 Ⓐ基本部品(2)


本章では、ユーザ認証と、キーイベントの処理、マウスイベントによるグラフィックス描画について学習する。ここで作成するアプリはここからダウンロードできる。

10.1.認証クラスの定義

 ユーザ認証クラス(オブジェクト)に最低限必要なのは、
  1. IDとパスワードの対の保存(管理)機能と、
  2. 与えられたIDとパスワードの対が登録されたものと一致するかを判定する認証機能
である。
メソッド説明
put(キー,値)対(キー,値)を登録する
containsKey(キー)キーを持つ対を含めば真
get(キー)キーと対になる値を取得する
remove(キー)キーを持つ対を削除する
 java.utilパッケージにあるHashMapクラスはキーと値の対を管理する右表のメソッドを持つ。このクラスを継承(拡張)して、ID(キー)パスワード(値)の対を登録し、メソッド 認証(ユーザ名,パスワード)を追加した認証器クラスとそのコンストラクタを以下のように定義できる。

public class 認証器 extends java.util.HashMap{
  認証器(){super();
    put("yamasaki","0000" );//ユーザIDとパスワードの対を登録
    put("saitou","1111" );//ユーザIDとパスワードの対を登録
  }
  //メソッド 認証(ユーザ名,パスワード):渡されたユーザ名とパスワードの照合
  public boolean 認証(String ユーザ名, String パスワード){
    return containsKey(ユーザ名) && パスワード.equals(get(ユーザ名));
  }
}

実習.以下の手順で、ユーザ認証クラスを作成する
1.クラス定義ファイルの作成
  Java→Javaメインクラスを選び、クラス名を 認証器 とする。
  (動作確認のため、メインクラスとして定義する)

2.前ページのクラス定義を参考に、
1)認証器クラスをHashMapの拡張(extends java.util.HashMap)として定義する
2)適当な ユーザ名 と パスワード の対を登録するコンストラクタを追加する
3)認証 メソッドを追加する

3.動作確認のため、mainメソッド内に例えば次のように記述する。
  認証器 利用認証 = new 認証器();
  System.out.println(利用認証.認証("yamasaki","0000"));
  System.out.println(利用認証.認証("yamasaki","1111"));

4.「ファイルを実行」して、結果を確認する。
問.パスワード として文字配列をとる 認証メソッドを追加せよ(次節で必要)
5.プログラムチップスを参考に、メソッドの空欄____を埋めて、追加せよ
  public boolean 認証(String ユーザ名, ____ パスワード){
    return containsKey(ユーザ名) 
        && String._______(パスワード).equals(get(ユーザ名));
  }

6.以下の命令文をmainメソッドに追加して、上のメソッドの動作確認をせよ
   char パス配列[]={'0','0','0','0'};
   System.out.println(利用認証.認証("yamasaki",パス配列));

プログラムチップス
1.キーと対の値の取得メソッドget(キー)は、キー を持つ対が含まれない(登録されていない)とnull値を返すので、あらかじめcontainsKey(キー)メソッドで調べておく。
2.文字列はStringクラスのオブジェクトなので(そのため型名が大文字で始まる)、文字列 sと tが等しいか否かの判定は、演算子==でなく、s.equals(t) とする。
3.文字配列(char[])や数値等を文字列(String)に変換するには、String.valueOf(・)を用いる。

10.2.認証パネルの作成

 認証パネルの作成を通して、1行入力に用いるJTextField、パスワード入力用のJPasswordFieldの使い方を学ぶ。JPasswordFieldの入力(textプロパティ)の取得には、セキュリティ上の理由から通常のgetText()ではなく文字配列を返すgetPassward()を使用する。

実習.以下の手順で、ユーザ認証パネルを作成する
1.9章と同様に、3枚のタブ付きパネルを作成し、変数名とタブテキストを適宜設定する。

2.オブジェクト 利用認証 の宣言と生成
プログラム最後尾に、NetBeansが自動生成したオブジェクト宣言部があるので、以下のように行を追加する。
  // End of variables declaration
  private 認証器 利用認証 = new 認証器();

3.ユーザ名入力のテキストフィールド(JTextField)とパスワード入力のパスワードフィールド(JPasswordField)、ラベルをパネルに追加し、変数名とテキストを適宜設定する

4.下の問のプログラムをパスワード入力のActionPerformedイベントハンドラに記述する

5.実行して結果を確認する
問.空欄(認証結果のメッセージ内容)を埋めてハンドラを完成させよ。
  String ユーザ名=(ユーザ名入力).getText(); //ユーザIDを取得
  char パス配列[] =(パスワード入力).getPassword();//パスワードを取得
  //認証成功
  if(利用認証.認証(ユーザ名,パス配列)) (ラベル).setText(____);
  //認証失敗
  else (ラベル).setText(____);
  jPasswordField1.setText("");

10.3.キーイベント処理

 キーボードをタイプした時のイベント(keyTyped)はその文字を教えるメソッド(char getKeyChar())を持ち、キーを指で押した時(keyPressed)や放した時(keyReleased)のイベントは、キーの番号を教えるメソッド(int getKeyCode())を持つ。この節では、キーイベント捉えるのに複数行の入力に用いるテキスト領域(JTextArea)を使用する。

実習.以下の手順でキーイベント処理のページを作成する
1.10.1で作成したタブ付きページ(パネル)に、テキスト領域とラベル 2個を追加し、変数名とテキストを適宜設定する
2.テキスト領域のKeyPressedイベントハンドラに次のように記述する
  int キーコード=evt.getKeyCode();
  String キー名=evt.getKeyText(キーコード);
  (ラベル1).setText("キー名:"+キー名+" ("+キーコード+")"); 

3.テキスト領域のKeyTypedイベントハンドラに次のように記述する
  char 文字=evt.getKeyChar();//入力された文字を取得
  int 文字コード=0+文字;
  (ラベル2).setText("文字:"+文字+" ("+文字コード+")");

4.「ファイルを実行(Shift+F6)」して、結果を確認せよ。
問.以下の問に答えよ
1.getKeyCode()とgetKeyChar()の相違点を述べよ
2.(0+文字) の値は何か。また値がそうなる理由を述べよ

10.4.マウスイベント処理とグラフィックス

マウスのドラッグに合わせて、始点とマウスの現在地点を結ぶ直線、その直線を対角線に持つ長方形、その長方形に内接する楕円を描画させてみよう。ここでは部品共通化の手法を理解するために、上記の機能を追加したパネル(JPanel)部品を新たに定義して、それをJFrameに組み込むという手順をとる。

1.描画メソッドの再定義
 ウィンドウの移動やサイズ変更等でディスプレイ上で表示を描き直す必要が生じたとき、内部的にpaint()あるいはpaintComponent()メソッドが呼ばれる。これを再定義(上書き)するとプログラムによる描画が可能になる。ただし、描画メソッドは必要が生じたときしか実行されない内部メソッドなので、描画させたいタイミングで再描画命令repaint()を出す必要がある。ここでは、パネル上に描画するので、以下のような変数宣言とメソッドを用意しよう。
int x1,y1,x2,y2; //ドラッグの開始座標(x1,y1)と現在座標(x2,y2)
public void paintComponent(java.awt.Graphics g){
//Graphicsオブジェクトは様々な描画機能を持つ
  super.paintComponent(g);// 背景をクリアする
  g.setColor(java.awt.Color.red);//赤色を設定
  if (x1>x2)      g.drawLine(x1,y1,x2,y2);//直線
  else if (y1<y2) g.fillRect(x1,y1,x2-x1,y2-y1);//矩形
  else            g.drawOval(x1,y2,x2-x1,y1-y2);//楕円
}

このように描画メソッド(paint(), paintComponent())では、
  1. Graphicsオブジェクトを引数に持つので、それを利用する
  2. 直線描画の引数は(始点x座標,始点y座標,終点x座標,終点y座標)である
  3. 矩形や楕円描画の引数は(左端x座標,上端y座標,幅,高さ)である
  4. 座標は左上が(0,0)で、正方向は右および下である
ことに注意しよう。
実習.マウスによる描画可能なパネルクラスの定義
1.NetBeansで新規ファイル→SwingGUIフォーム→JPanelフォームを選ぶ。
 クラス名はデフォルトで NewJPanel となる。問題がなければそのまま[終了]
2.ソース中の適切な位置、例えば
  // End of variables declaration
の直後に前ページの変数宣言とpaintComponentメソッドを挿入する。
3.パネルのMousePressedイベントハンドラに次のように記述する
  x1=evt.getX(); y1=evt.getY();//マウスのXY座標を取得
4.パネルのMouseDraggedイベントハンドラに次のように記述する
  x2=evt.getX(); y2=evt.getY();//マウスのXY座標を取得し
  repaint();//paintComponent()で(再)描画
5.パネル部品は単独では実行できない。[構築]→「"NewJPanel.java"をコンパイル F9」でコンパイルしてエラーがあったら修正しておく。
注.実習にはないが、JPanelに部品を載せる場合はnullレイアウトにするとよい

2.描画機能を持ったパネルの追加
 上で作成したパネル(NewJPanel)を組み込むには、通常の手順でパネルを配置した後、そのコンストラクタにNewJPanel()を使用する。

実習.以下の手順で描画機能を持つパネルを組み込もう
1.タブ付きページを用意してなければ、JPanelを追加する。
2.パネルの[コード]中のカスタム作成コードの[…]ボタンを押し、現れたエディタ上で次のように記述する。
  new NewJPanel();
これによって、パネルがNewJPanelクラスのオブジェクトとして生成される
注.パネル(JPanel)とそれが載っているタブ付枠(JTabbedPane)を混同しないようにしよう。上記の命令をタブ付枠のカスタム作成コードに記述してしまうと、
  1. ソースコード上では、エラーが見えないが、エラーで実行できない。
  2. 実は、initCompnentsメソッドを展開すると、例えば
      jTabbedPane1= new JPanel();
    と記述されていて、そこがエラーになっている
ので、2.と同様の操作で記述をここから削除しパネルの作成コードに移す
3.「ファイルを実行 Shift+F6」して正しく働くことを確認する。
4.描く図形を、直線および塗りつぶされていない矩形および塗つぶされている楕円に変えよ。

まとめ

本章で利用した部品とプロパティ、イベント、メソッドを以下の表にまとめている。自分の理解を確認しよう。

部品・クラスプロパ
ティ
イベントメソッド
JTextFieldtextactionPerformedString getText()
JPasswordFieldtextactionPerformedchar[] getPassword()
(JTextArea)---ketPressed
keyTyped
int getKeyCode()
String getKeyText(int code)
char getKeyChar()
(JPanel)---mousePressed
mouseDragged
int getX(), int getY()
java.awt.Graphics------ void setColor(java.awt.Color c)
void drawLine(x1,y1,x2,y2)
void drawRect(x1.y1,w,h)
void drawOval(x1.y1,w,h)
void fillRect(x1.y1,w,h)
void fillOval(x1.y1,w,h)

課題

今回の課題にしたがって、プログラムを完成させよ。

第11章 Ⓐコマンドによる部品追加

 NetBeansによるウィンドウアプリケーションの作成で命令を記述するのは、イベントハンドラの中身だけであった。部品の配置やプロパティ設定、イベントの登録などに関する命令(記述)は、すべてNetBeansによって自動生成された。しかし、8章でも見たように、ウィンドウアプリケーションであっても一からすべてプログラミングすることができる。この章ではその方法について学ぶ。作成するアプリはこちらからダウンロードできる。

11.1.ウィンドウプログラムの分析

例えば カウンタ という名で、新しいJFrameクラスを作成しよう。次ページのプログラムはいわゆるカウンタアプリケーションで、
  1. フレームに境界線レイアウト(BorderLayout)を設定し
  2. ボタンを右に、ラベルを中央に配置し
  3. ボタンの変数名とtextを「カウント」
    ラベルの変数名を「数ラベル」、textを「0」に設定し
  4. 「カウント」ボタンのクリックで「数ラベル」に表示される値を1増やす
このうち、実際に我々が記述するのは、赤字の1行だけで、他はすべてNetBeansが生成した文である(一部を…で省略し、説明のためにコメントを付加した)。
 しかし、「カウント」ボタン(ラベルも)に関わる次の命令文を適切な位置に直接記述すれば、NetBeansに頼らず「カウント」ボタンを配置し機能させられる筈である。

宣言 private javax.swing.JButton カウント;
生成 カウント = new javax.swing.JButton();
プロパティ設定 カウント.setText("カウント");
イベントハンドラ登録
カウント.addActionListener(new java.awt.event.ActionListener(){
 public void actionPerformed(java.awt.event.ActionEvent evt){
  カウントActionPerformed(evt);}
});
配置 getContentPane().add(カウント,java.awt.BorderLayout.RIGHT);
イベントハンドラの記述
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
 数ラベル.setText(Integer.parseInt(数ラベル.getText())+1+"");
}

public class カウンタ extends javax.swing.JFrame {
  public カウンタ() { initComponents(); }//コンストラクタ
  private void initComponents() {//コンストラクタの本体:編集不可
    カウント = new javax.swing.JButton();
    数ラベル = new javax.swing.JLabel();
    setDefaultCloseOperation(…);
    //ボタンのプロパティ設定とイベントハンドラ登録、配置
    カウント.setText("カウント");
    カウント.addActionListener(new java.awt.event.ActionListener(){
      public void actionPerformed(java.awt.event.ActionEvent evt){
      カウントActionPerformed(evt);}
    });
    getContentPane().add(カウント,java.awt.BorderLayout.LINE_END);
    //ラベルのプロパティ設定と配置
    数ラベル.setText("0");
    getContentPane().add(数ラベル, java.awt.BorderLayout.CENTER);
    pack();
  }
  //ボタンのイベントハンドラの実体
  private void カウントActionPerformed(java.awt.event.ActionEvent evt){
    数ラベル.setText(Integer.parseInt(数ラベル.getText())+1+"");
  }
  public static void main(String args[]){
    java.awt.EventQueue.invokeLater(new Runnable(){
      public void run() {new NewJFrame().setVisible(true);}
    });
  }
//使用部品の宣言
  private javax.swing.JButton カウント;
  private javax.swing.JLabel 数ラベル;
}


 次節以降、このプログラムに命令文を追加していく。  

11.2.インポート文

 部品を配置し機能させる命令を直接入力する際、クラス名の前につける javax.swing.、java.awt.、java.awt.event. などのパッケージ指定をいちいち記述するのは面倒だし、間違いのもとである。まずこれを避けておこう。
  import javax.swing.*;
  import java.awt.*;
  import java.awt.event.*;
などのインポート文をプログラムの頭に記述すると、それぞれ javax.swing.、java.awt.、java.awt.event. を省略し、例えば、
  private javax.swing.JButton カウント; を
  private JButton カウント;       と書ける。

実習.import文の追加
前節のプログラムの最初に、上で説明したimport文を挿入せよ

11.3.クリアボタンの追加

 11.1節の分析を参考に、「数レベル」の表示を「0」にする「クリア」ボタンを追加しよう。その際、より簡潔な記述を解説する。

ボタン クリア の生成
   private JButton クリア = new JButton("クリア");

この文は「クリア」ボタンに関する次の3つを一度に行う。
・定義 private javax.swing.JButton クリア;
・生成 クリア = new javax.swing.JButton();
・テキスト設定 クリア.setText("クリア");

ボタン クリア の配置
   getContentPane().add(クリア, BorderLayout.LINE_START);

この文はフレームの左端にクリアボタンを配置する。

クリアハンドラの設定
   クリア.addActionListener( evt -> {
     数ラベル.setText("0");
   });
この文はJavaのラムダ式を用いて、以下のプログラムと同等の働きをする。
  クリア.addActionListener(new java.awt.event.ActionListener(){
    public void actionPerformed(java.awt.event.ActionEvent evt){
      クリアActionPerformed(evt);}
  });
  //クリアボタンのイベントハンドラの実体
  private void クリアActionPerformed(java.awt.event.ActionEvent evt){
    数ラベル.setText("0");
  }
 
実習.クリアボタンの追加
以下のプログラムを参考に、上記の文を記述してクリアボタンを追加せよ。
    private JButton クリア = new JButton("クリア");
    /** Creates new form カウンタ... 3行*/
    public カウンタ() { initComponents(); 
      //initComponentは直接編集できないので、以下に記述
      getContentPane().add(クリア, BorderLayout.LINE_START);         
      クリア.addActionListener( evt -> {
        数ラベル.setText("0");
      });
    }
コラム.Javaのラムダ式
関数 f(x)=x2
関数定義int f(int x){ return x*x}
  参照f(x)
ラムダ式IntFunction f = x -> x*x;
  参照f.apply(x)
 ラムダ式はメソッド(関数)の実体をメソッド名と分離して定義する式で
  (変数リスト) -> {定義本体}
という形をとる。Javaのラムダ式は関数インターフェースの実装として使われ、推測可能な括弧や型定義を省力した簡潔で分りやすい記述ができる。
ハンドラ記述
  クリア.addActionListener(new java.awt.event.ActionListener(){
    public void actionPerformed(java.awt.event.ActionEvent evt){
      数ラベル.setText("0");
  }});
の場合、addActionListenerの変数はメソッドactionPerformed(ActionEvent evt)を持つActionListenerなので、それらを省略した記述ができる。  
  クリア.addActionListener( evt -> {
    数ラベル.setText("0");
  });

11.4.数字ボタンの追加

 前節の「クリア」ボタンは、NetBeansの機能を使っても実現でき、直接プログラムするメリットはあまりないかも知れない。本節では、0~9の数字ボタン列を載せたツールバーを配置し、クリックでの数字入力を可能にしてみよう。

ツールバーの生成
  private JToolBar ツールバー = new javax.swing.JToolBar();

ツールバーを下部に配置
  getContentPane().add(ツールバー, BorderLayout.PAGE_END);

数字ボタン配列の生成
  private JButton 数字[] = new JButton[10];

各数字ボタン(配列要素)の生成配置・ハンドラ登録
  for (int i=0; i<=9; i++){
    数字[i]=new JButton(i+"");//ボタン配列要素の生成とテキスト設定
    ツールバー.add(数字[i]);//ツールバーにボタンを配置
    数字[i].addActionListener( evt -> {//ハンドラの本体
      for(int k=0; k<=9; k++) if(evt.getSource()==数字[k]) 
        数ラベル.setText((数ラベル.getText()+k).replaceFirst("^0+", ""));
    });
  }
 ポイントは、ボタン配列(JButton 数字[])で実現することにより、10個のボタン(数字[0]~数字[9])の生成・配置・ハンドラ登録をまとめて(for文で)記述できる点にある。その場合、10個のボタンの各々で異なる数字を付加する必要があるが、各々に異なるハンドラは登録できない。それを、イベントの発生源を取得するgetSource()メソッドが可能にしている。
 また、replaceFirst("^0+", "") は先頭の 0 を空白に置換する。

実習.数字ボタンの追加
上の説明にしたがって、ツールバーと10個の数字ボタンを配置し、ボタンクリックで数字を付加できるように、プログラムに命令文を追加せよ。

プログラムチップス
1.import 文を使うとパッケージ指定を省略できる
2.イベントevtの発生部品(オブジェクト)は evt.getSource(); で取得する
3.部品をJFrameに配置するには getContentPane().add(部品,配置位置) とする
4.部品Aに部品Bを配置するにはA.add(B)とする

課題

本章の実習プログラムを完成させよ。

12章 簡易エディタ

 本章では最終課題である簡易エディタの作成に向けて、以下のようにメニューテキストエリアの活用方法、ダイアローグの表示方法について学ぶ。操作説明は、これまでの復習もかねて基本から説明しているが、詳細については以前の章を参考にしてほしい。
 簡易エディタはここからダウンロードして利用できる。

実習.準備(クラス名等は例示なので適宜設定せよ)
簡易エディタのために新たにプロジェクトとメインのプログラムファイルを作成しよう。NetBeansを起動したら
1.新規プロジェクトの作成
・ファイル→新規プロジェクト→Java→Javaアプリケーション→[次へ]
・プロジェクト名:簡易エディタ
 プロジェクトの場所:講義用フォルダー
 主クラスを作成のチェックをはずして
 [終了]
2.新規ファイルの作成
・ファイル→新規ファイル→JavaGUIフォーム→JFrameフォーム→[次へ]
・クラス名:簡易エディタ
 [終了]
3.主クラスファイルの設定
・プロジェクトを右クリック→プロパティ→実行
 主クラスに上で作成したクラスを指定し、[了解]
これによって、「プロジェクトを実行(F6)」で指定した主クラスが翻訳・実行される

12.1.メニューの構造

メニュー(JMenu)を並べるバー(横木)をメニューバー(JMenuBar)といい、メニューを選択したとき現れる項目をメニュー項目(JMenuItem)という。また、メニューがその中にメニュー(中にメニュー項目を持つ)を持つこともできる。
すなわち、メニューは
(1)メニューバーがあり、
(2)メニューバー上に複数のメニューが並び、
(3)(メニューをクリックすると)メニュー内のメニュー項目やメニューが並ぶ
という階層構造を持つ。

実習.部品配置とプロパティ設定(変数名等は例示なので適宜設定せよ)
1.フレームのレイアウトを境界線レイアウト(BorderLayout)に設定
  JFrame上で右クリック→レイアウトを設定→境界線レイアウト
2.部品配置とプロパティ設定
テキストエリア(JTextArea)を中央に配置し変数名「編集領域」と設定
メニューバーを配置
・メニューの追加(3個)
  メニューバーを右クリック→メニューの追加
  メニューの変数名と textをそれぞれ「編集」、「書式」、「ヘルプ」と設定
・メニュー項目の追加方法
  メニューを右クリック→パレットから追加→メニュー項目
 以下のメニュー項目を追加し、変数名と textを以下のように設定
  編集メニューに3項目追加:「切取」、「コピー」、「貼付」
  書式メニューに1項目追加:「折返し」
  ヘルプメニューに1項目追加:「バージョン」

変数名と textの設定手順:変数名や textプロパティはNetBeansが勝手に付けるが、以下の方法で分かりやすいもの変更できる。
  • 変数名:対象を右クリック→変数名を変更…
  • textプロパティ:対象を右クリック→テキストを編集

12.2.イベントハンドラ

 メニュー項目に対するactionPerformedイベントのハンドラを作成しよう。編集メニューの各項目には、それぞれ対応するメソッドcut()、copy()、paste()がJTextAreaに備わっていて、それを利用する。右端で「折返し」か否かは、JTextAreaのlineWrapプロパティの真偽で決まるので、ハンドラは、その値を取得getLineWrap()し、真偽を反転(否定 !)して再設定setLineWrap()する。「バージョン」のハンドラは、バージョン情報のメッセージダイアローグを表示する。
 なお、メニューバーやメニューはメニュー項目の入れ物なので、そこにイベントハンドラを設定しても通常意味がないことに注意しよう。

実習.actionPerformedイベントハンドラの作成
1.編集メニューの各項目
 メニュー項目「切取」のactionPerformedイベントを「切取ハンドラ」という名前で登録し次のように記述する(灰色部はイベント登録で作成させる)
  private void 切取ハンドラ(java.awt.event.ActionEvent evt) {
     編集領域.cut();
   }                                                                       
「コピー」(copy())や「貼付」(paste())も同様に記述する。
2.メニュー項目「折返し」
  private void 折返しハンドラ(java.awt.event.ActionEvent evt) {
     編集領域.setLineWrap(! 編集領域.getLineWrap());
   }                                                                        
3.メニュー項目「バージョン」
 「バージョン情報」ダイアローグを表示させるために以下のように記述する。
ダイアローグのタイプやタイトル、メッセージ内容は適宜書き換えてみよう。
  private void バージョンハンドラ(java.awt.event.ActionEvent evt) {
javax.swing.JOptionPane.showMessageDialog(this, 
  "Version 1\n Hideki Yamasaki\n 2019/6",//メッセージ
  "簡易エディタ", //タイトル
  javax.swing.JOptionPane.INFORMATION_MESSAGE); //タイプ
   }                                                                     

イベントハンドラ名の設定手順:イベントハンドラ名は何もしないとNetBeansが勝手に付けるので、以下の方法で設定・変更する。
  • 設定:イベントの対応する欄の[…]をクリック→追加→新規ハンドラ名
  • 変更:イベントの対応する欄の[…]をクリック→名前の変更

課題

アプリケーションを完成させよ。その際、ヴァージョン情報を適切に変更せよ。さらに、編集機能(切取、コピー、貼付)を実装したボタン(JButton)を載せたツールバー(JToolBar)を組み込め。

コラム.オブジェクトのプロパティへのアクセス
オブジェクトのプロパティは、通常、直接アクセスを禁じて、用意されている読取メソッド【getプロパティ名()】と設定メソッド【setプロパティ名()】を介して行う。したがって、値を変えられては困るプロパティには設定メソッドが提供されない。

コラム.名前(オブジェクト名・メソッド名)の変更
上の課題にある編集ボタンを作成する際、これまでと同じやり方をすると、メニュー項目用とボタン用でまったく同じ動作をするハンドラを2つ作ることになる。これは無駄なので、両者で共通のメソッドを利用する手順を「切取」を例に説明する。
  1. 既存メソッドの利用
    ボタン「切取」を選択し、actionPerformedイベントの【…】をクリックしてカスタムエディタを開く
    メソッドがすでに登録されていれば【削除】し、【追加】をクリックして、既存のハンドラ名「切取ハンドラ」を登録する

コラム.メニュー項目へのシュートカット設定手順
設置したメニュー項目にはショートカット欄があり、そこをダブルクリックすると Acceleratorウィンドウがを開く。例えば Ctrl+Z を設定するには、仮想キーで VK_Z を選び □Ctrl にチェックを入れればよい。

第13章 ファイル入出力

本章では、Javaにおけるファイルとの入出力の基本について学ぶ。ファイル入出力では、3章で説明した例外処理をしなければ文法エラーになる(章末コラムを参照)。例外処理ではエラーメッセージを載せたダイアログを表示するようにしよう

13.1.ファイルの入出力メソッド

1 ファイルへの書出し
 「ファイル」に「編集領域」の内容を書出すメソッド書出(ファイル,編集領域)は例外処理を加えて、以下のようになる。編集領域の内容(改行を含む文字列)をそのままファイルに書き出すために
  1. File ファイル から文字単位の書出し機能を持つ FileWriter (オブジェクト)を生成する
  2. FileWriter から行単位の書出し機能を持つ BufferedWriter を生成する
  3. BufferedWriter から全体の書き出しメソッド write(String s) を持つ PrintWriter 版ライタ を生成する
  4. 版ライタ のwriteメソッドに 編集領域 のテキストを取得して渡す
  5. 版ライタ(ファイル) を閉じる
という手順を踏む。

private void 書出(java.io.File ファイル,javax.swing.JTextArea 編集領域){
 try{//PrintWriterを作成してJTextAreaの内容をまとめて書出す
  java.io.PrintWriter 版ライタ =
      new java.io.PrintWriter(
          new java.io.BufferedWriter(
              new java.io.FileWriter(ファイル)));
  版ライタ.write(編集領域.getText());
  版ライタ.close();
 }catch(Exception 例外){
  javax.swing.JOptionPane.showMessageDialog(this,
  "IOエラー","簡易エディタ",javax.swing.JOptionPane.ERROR_MESSAGE);
 }
}
注.実は、PrintWriterはFileから直接生成できるので
   java.io.PrintWriter 版ライタ = new java.io.PrintWriter(ファイル);
とすることもできるが、次の読込みメソッドとの関連で細かな手順を踏んでいる。
2 ファイルからの読込み
 ファイルから編集領域に読込むメソッド読込(ファイル,編集領域)は例外処理を加えて、以下のようになる。ファイルからの読込みには、書出しのように全部まとめて読込む機能を持つクラスはないので、行単位の読み取り機能を持つBufferedReaderクラスを使って1行ずつ読み取ることにする。
  1. File ファイル から文字単位の読込み機能を持つ FileReader (オブジェクト)を生成する
  2. FileReader から行単位の読み取り機能 readLine() を持つ BufferedReader 行リーダ を生成する
  3. 行リーダ.readLine() を使って読込んだ 行 が空(null)でない間、行 を順に 編集領域 に付け加える
  4. 行リーダ(ファイル)を閉じる

private void 読込(java.io.File ファイル,javax.swing.JTextArea 編集領域){
 try{//BufferedReaderを作成して1行ずつ読込んではJTextAreaに追加
  java.io.BufferedReader 行リーダ = 
      new java.io.BufferedReader(
          new java.io.FileReader(ファイル));
  編集領域.setText("");
  for(String 行;
      (行=行リーダ.readLine())!=null;//読込んだ行がnullでない間
      編集領域.append(行+"\n")){ }//行(+改行) を編集領域に追加
  行リーダ.close();
 }catch(Exception 例外){
  javax.swing.JOptionPane.showMessageDialog(this,
  "IOエラー","簡易エディタ",javax.swing.JOptionPane.ERROR_MESSAGE);
 }
}
注.Java7から追加されたクラスを使えば、まとめて読込むこともできる。
編集領域.setText(new String(java.nio.file.Files.readAllBytes(
java.nio.file.Paths.get(ファイル.getAbsolutePath()))));


コラム.オブジェクトの作成
あるクラスのオブジェクトは new クラス名(・); で作成される。さらに、他で使うためにそのオブジェクトに名前を付ける場合は クラス名 オブジェクト名 = new クラス名(・); とする。
また、例題のプログラムでクラス名の前に java.io. 等とあるのは、そのクラスが属する(定義されている)パッケージの指定である。
コラム.例外(エラー)処理
入力処理などでは、読み込みに関わるエラーが生じる可能性があり、その対策を講じなければならない。これを例外処理といい、次の形式をとる。
try {
   //例外(エラー)が発生する可能性のある部分
} catch (例外のクラス 例外) {
   //例外に対する処理
}
こうすると、try部で例外(エラー)が発生したとき(だけ)catch部の例外処理が行われ、その後、try-catch部の次から計算を継続する。

コラム.for文:繰り返し
for (初期設定;繰り返し条件;更新処理) {・・・}

と書くと、
  ①「初期設定」を実行
  ②「繰り返し条件」を調べ、YESならば③へ、NOならばこのfor文を抜ける
  ③ 繰り返し部分 {・・・} を実行
  ④「更新処理」を実行して②へ
という意味になる。例題では { } 内が空である。
注.{・・・}の中が1文だけのときは、中括弧 { と }を書かなくてもよいので、例題の { } は単に ; としてもよい。

13.2.ファイルメニューの作成

 ファイルメニューには通常、「新規」、「開く」、「保存」、「名付け保存」、などの項目がある。ファイルメニューの各項目とそのイベントハンドラを作成しよう。
1.メニューバーにメニューを追加し、変数名とtextを「ファイル」とする(すでにあれば不要)
2.ファイルメニューに「新規」、「開く」、「保存」、「名付け保存」の(変数名とtextを持つ)メニュー項目を追加する
3.JFileChooserを次の手順で追加し、変数名を ファイル窓 とする
  ナビゲータ(インスペクタ)ウィンドウ→他のコンポーネントを右クリック
  →パレットから追加→Swingウィンドウ→ファイルチューザ(JFileChooser)
4. File オブジェクト ファイル を宣言し、初期値 null を設定するため、オブジェクトの宣言をしている場所の最後に、以下の文を付け加える
// End of variables declaration
  private java.io.File ファイル = null;
5.4の文に続けて、13.1節の 書出 と 読込 メソッドを付加する

メニュー項目「新規」のイベントハンドラ
 ファイル を空にして、JFrameのタイトルを変更し、編集領域をクリアする
  private void 新規ハンドラ(java.awt.event.ActionEvent evt) {
  ファイル=null;
  setTitle("簡易テキストエディタ 無題.txt");
  編集領域.setText("");
   }                                                                        

メニュー項目「開く」のイベントハンドラ
 ファイル選択ウィンドウ(JfileChooser) ファイル窓 の OpenDialog を表示し、選択されたファイルから読込む
  private void 開くハンドラ(java.awt.event.ActionEvent evt) {
  if (ファイル窓.showOpenDialog(this)
        ==javax.swing.JFileChooser.APPROVE_OPTION){
    ファイル=ファイル窓.getSelectedFile();
    setTitle("簡易テキストエディタ "+ファイル.getName());
    読込(ファイル,編集領域);
  } 
   }                                                                        
メニュー項目「名付け保存」のイベントハンドラ
 ファイル窓のSaveDialogを開き、選択されたファイルに書き出す

メニュー項目「保存」のイベントハンドラ
 「保存」では、ファイルが空(null)の場合は 名付け保存ハンドラ を実行し、空でない場合は単に 書出(ファイル,編集領域) メソッドを実行する

問.「名付け保存」と「保存」のハンドラを以下の要領で作成せよ
1.「開く」のハンドラを参考に空欄_____を埋めよ
  private void 名付け保存ハンドラ(java.awt.event.ActionEvent evt) {
  if (ファイル窓.showSaveDialog(this)
      ==javax.swing.JFileChooser.APPROVE_OPTION){
    ファイル =__________.____________;
    setTitle("簡易テキストエディタ " +___________);
    ______________________;
  }
   }                                                                        

2.上の説明を参考にメニュー項目「保存」のハンドラを作成せよ
  private void 保存ハンドラ(java.awt.event.ActionEvent evt) {
    if (ファイル==null) ___________________;
    else _______________________;
   }                                                                        

課題

以上の説明を参考に、簡易エディタに「保存」を含めたファイル入出力機能を追加したプログラムを作成しよう。

コラム.if文とelse文:条件分岐
    if (条件式) {・・・}
と書くと、「条件式が成り立つときだけ {…} の内部を実行せよ」という意味になる。条件式は必ず括弧の中に入れなければならない。else文はif文の直後に
    else {・・・}
と書いて「直前のif文の条件式が成り立たなければ {・・・} の内部を実行せよ」という意味になる。
注.{・・・}の中が1文だけのときは、中括弧 { と }を省略してもよい。

A==BAとBが等しい
A!=BAとBが等しくない
A<BAはBより小
A>BAはBより大
A<=BAはB以下
A>=BAはB以上
 条件式の基本は右表のような二つの式の値を比較する式である。さらに、条件式は論理演算の かつ(&&)、または(||)、でない(!)を使って組み合わせることができる。その際、条件式を括弧(、)で括る必要がある。

第14章 簡易エディタの拡張

最終課題は、作成してきた簡易エディタに便利と思われる機能を追加することである。そのためのヒントをいくつかあげる。
詳しくはJavaのAPI仕様を参考にせよ。
サンプルファイル:実行形式簡易エディタJavaファイルフォントチューザーJavaファイル、(2つのJavaファイルを同一フォルダに置けば0.2節の手順で翻訳・実行できる)Formファイル(NetBeansがデザインの編集に用いる)

1.Undo、Redoの実現

編集操作のUndo(取消)、Redo(復活) 機能を実現するには、取消可能な編集操作を管理するオブジェクトが必要である。そのため、UndoManagerクラスを利用する。
 (1)まず以下の文をプログラムの最後尾に追加しよう
//UndoManager 取消管理器 の生成
private javax.swing.undo.UndoManager 
   取消管理器=new javax.swing.undo.UndoManager();
//取消可能操作を発生時に 取消管理器 に記録するクラス 操作聴取路 を定義
private class 操作聴取路 implements 
  javax.swing.event.UndoableEditListener {
    public void undoableEditHappened(
      javax.swing.event.UndoableEditEvent 操作){
        取消管理器.addEdit(操作.getEdit()); //編集操作の記録
      }
}
 (2)操作聴取路 を編集領域の文書に追加する命令を簡易エディタのコンストラクタ内に追加すると、編集領域 での取消可能操作が 取消管理器 に記録されるようになる。
public 簡易エディタ() {
  initComponents();
  編集領域.getDocument().addUndoableEditListener(new 操作聴取路());
}
 (3)上記の 準備のもとに、取消と復活のメニュー項目を作成し、それらのイベントハンドラ(メソッド)にそれぞれ
    if (取消管理器.canUndo()) 取消管理器.undo();
    if (取消管理器.canRedo()) 取消管理器.redo();
と記述すればよい。

2.テキストエリアのフォント変更

 JTextAreaのsetFont(Font)メソッドを
編集領域.setFont(new java.awt.Font(
      "HGP行書体",//フォント名
       java.awt.Font.BOLD+java.awt.Font.ITALIC, //スタイル
       24 ));//サイズ
のように呼ぶ。
 注意:文字列単位でフォントの変更(指定)ができるわけではない。
現在のフォント名やスタイル、サイズはそれぞれ
  編集領域.getFont().getFontName(),
  編集領域.getFont().getStyle(),
  編集領域.getFont().getSize()
で取得できるので、例えばフォント名だけを変えたければ
 編集領域.setFont(new java.awt.Font(
   "HGP行書体", //編集領域.getFont().getFontName(),
   編集領域.getFont().getStyle(),
   編集領域.getFont().getSize() ));
とすればよい。
.文字列単位でフォントを指定する機能は JTextArea にはないので、例えばこちらを参考に最初から作り直す必要がある。また、JAVA(NetBeans)には、フォント選択ダイアローグを表示してフォント選択を許すクラスはないので、第三者が作成したクラスを探して利用する(か、自分でそれに代わるもの作る)必要がある。

3.定例文の記入

 文 (文字列)は 編集領域 の最後に追加(編集領域.append(文);)あるいはカーソル位置に挿入(編集領域.replaceSelection(文);)できる。メニュー項目「日付」を作りそのハンドラで以下のように記述すると、今日の日付をDateFormat.FULL書式で 編集領域 に追加できる。
編集領域.append(java.text.DateFormat.getDateInstance(    java.text.DateFormat.FULL).format(new java.util.Date())+"\n");

4.印刷機能

JTextAreaのprint()メソッドを利用する。ファイル入出力と同様に例外処理が必要になる。

5.文字と背景の色設定

JColorChooser 色窓 をJFileChooserを追加したときのように「他のコンポーネント」として追加し、適当なメニュー項目を配置しそのイベントハンドラに(それぞれ)以下のように記述する
編集領域.setForeground(色窓.showDialog(this,
    "文字色",java.awt.Color.black));
変種領域.setBackground(色窓.showDialog(this,
    "背景色",java.awt.Color.white));

6.文字数のカウント

JTextAreaの文字列の長さは、例えば 編集領域.getText().length() とすれば得られる。ただし、この長さには空白・改行文字も含まれる。

7.ファイルチューザーの設定

ファイル窓 を開いたときの ファイル名とファイルタイプを指定するには例えば以下のようにする。
 ファイル窓.setFileFilter(new javax.swing.filechooser.
   FileNameExtensionFilter("テキストファイル", "txt"));
 ファイル窓.addChoosableFileFilter(new javax.swing.filechooser.
   FileNameExtensionFilter("HTMLファイル", "html", "htm"));
 ファイル窓.setSelectedFile(new java.io.File(
   java.text.DateFormat.getDateInstance(java.text.DateFormat.FULL).
     format(new java.util.Date())+".txt"));//日付.txtをファイル名に設定

面接授業提出課題3

次のプログラムを提出せよ。
提出方法:yamasaki.hideki@ouj.ac.jpへのメール内への記述(コピペ)
提出期限:1週間以内
メールタイトル:Javaプログラミング入門提出課題3
メール内容:学生番号、氏名、プログラムの説明(プログラム中に記入してよい)
  1. 簡易エディタのプログラムに適当な拡張を施したもの


質問等は yamasaki.hideki@ouj.ac.jp までメールで。