広告

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■
                      2011年12月06日

   Java総合講座 - 初心者から達人へのパスポート
                 2009年11月開講コース 047号

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■□■□■□■□■□■□■□■□■□■□■□■□■□■□■


-------------------------------------------------------
・現在、このメールマガジンは以下の2部構成になっています。
[1] 当初からのコース:vol.xxx(xxxは番号)が振られています。
   これは現在、中級レベルになっています。
[2] 2009年11月開講コース:xxx号(xxxは番号)が振られています。
   これは現在、初心者向けのレベルになっています。
・このメールマガジンは、画面を最大化して見てください。
小さな画面で見ていると、不適切な位置で行が切れてしまう
など、問題を起すことがあります。
・このメールマガジンに掲載されているソース・コード及び
文章は特に断らない限り、すべて筆者が著作権を所有してい
ます。また、これらのソース・コードは学習用のためだけに
提供しているものです。
-------------------------------------------------------


========================================================
◆ 01.データベースを使用するアプリケーションの開発(続き)
========================================================


前回でお膳立てが整いましたので、今回はGUI側の編集をして
いきます。

HumanResourceEntryPane.javaをエディター(WindowBuilder Editor)
で開いてください。


ところで、このHumanResourceEntryPaneのソース・コードを見ると、
おそらく、警告のマーク(橙色のマーク)が付いているimport文
があるでしょう。そこにマウス・ポインターを持っていくと、
「インポートされた○○○は1度も使用されていません」という
メッセージが表示されますね。

┌補足─────────────────────────┐
警告のマークが付いている行がどこにあるのか探しづらい場合
は、右側の(縦長の)スクロール・バーの右側に橙色の帯がつ
いているところがありますので、そこにスライダーの中心を合
わせてみて下さい。ソース・コードが警告のマークのある位置
にスクロールされます。(ただし、そもそも警告のマークが付
いていなければ橙色の帯も表示されません。)
└───────────────────────────┘

これは、ソースを編集しているうちに不要になったimport文です
ので、削除しておきましょう。(そのままほったらかしておいて
も問題はないが、削除したほうがすっきりする。)

あるいは、どの行が不要になったのかを念のために(記念に?)
記録しておきたいという人は、この行をコメント(行の先頭に//
を入れる)にしておいてもいいです。

手で//を入力してもいいですが、その行のどこかにカーソルが入っ
ている(あるいはそのどこかが選択状態になっている)状態で、
Ctrl+/する(Ctrlキーをおしながら/キーを押す)という操作で、
行の先頭に//を入れることができます。(さらに、再度Ctrl+/する
と今度は//が外れます。)

その後、保管しておきましょう。



では、HumanResourceEntryPaneの「検索」のページを開いてください
(Designビューの画像の中の「検索」タブをダブル・クリックする)。

「検索」ボタンの下にJTableを貼り付けることにしましょう。
ただし、JTableに表示するデータ量が多いときにはスクロールできる
ようにしておく必要がありますから、スクロール機能をつけておきたい
ですね。
そのために、あらかじめJScrollPane(JScrollPaneはスクロールのでき
る平板状のGUI部品です)を貼り付けてから、その中にJTableを貼り付け
るようにしたいと思います。

では、まず「検索」ボタンの土台になっているJPanelをクリックして
下さい。その左側の縦方向の帯に0, 1, 2, 3と行の番号が表示されま
すね。その3の下の何も番号が表示されていないところを右クリックし、
「Append Row」を選択して下さい。
そうすると、先ほどのJPanelの下に行が追加されます。

では、Palette(パレット)のContainersの配下から「JScrollPane」を
選択して、その追加された行の左端(「column 0, row 4」が表示される
位置)に貼り付けましょう。
そして、その右端のハンドルを右方向にドラッグして、目いっぱい(5セル分)
幅を広げておきましょう。

続いて、このJScrollPaneの中にJTableを貼り付ける作業です。
Palette(パレット)のComponentsの配下から「JTable」を選択
して、このJScrollPaneの中の「View port」と表示される位置
に貼り付けましょう。


さて、今回のアプリケーションではデータベースにアクセスするため
に、先日作成したEmployeeDbManagerクラスを使用します。

そこで、このHumanResourceEntryPaneのソースの中に下記のような
getEmployeeDbManager()というメソッドを書き加えておきましょう。

--------------------------------------------------------
private EmployeeDbManager getEmployeeDbManager() {
   if (employeeDbManager == null) {
      employeeDbManager = new EmployeeDbManager();
   }
   return employeeDbManager;
}
--------------------------------------------------------

なお、これに合わせてソースの先頭のフィールドの定義が並んでい
るところに

--------------------------------------------------------
private EmployeeDbManager employeeDbManager = null;
--------------------------------------------------------

というようなフィールドの定義のコードを追加しておきます。


同様に、先日作成したTableModelOfEmployeeクラスを使用できるように
するために、

--------------------------------------------------------
private TableModelOfEmployee tableModelOfEmployee = null;
--------------------------------------------------------

というようなフィールドの定義と

--------------------------------------------------------
private TableModelOfEmployee getTableModelOfEmployee() {
   if (tableModelOfEmployee == null) {
      tableModelOfEmployee = new TableModelOfEmployee();
   }
   return tableModelOfEmployee;
}
--------------------------------------------------------

というようなメソッドのソース・コードも追加しておきましょう。



では次に、このtableModelOfEmployeeを先ほど貼りつけたJTableに結び付けて
おきましょう。
ソース・コード内の

--------------------------------------------------------
private JTable getTable() {
   if (table == null) {
      table = new JTable();
   }
   return table;
}
--------------------------------------------------------

を下記のように編集しましょう。

--------------------------------------------------------
private JTable getTable() {
   if (table == null) {
      table = new JTable(getTableModelOfEmployee());
   }
   return table;
}
--------------------------------------------------------
(編集するのはif文のブロックの中のJTableのコンストラクターの引数だけ
です。)
つまりJTableのコンストラクターの引数としてtableModelOfEmployeeを渡します。



続いて、「検索」ボタンをクリックしたときの動作のプログラミングをしましょう。
まず、Designビューの画面上で(「検索」タブのページの)「検索」ボタンを右クリッ
クして、「Add event handler」→「アクション」→「actionPerformed」を選択し、
getButton_1()メソッドの中に生成されたactionPerformed()メソッドの中に
下記のようなコードを追加しましょう。

--------------------------------------------------------
String name = textField_2.getText();
if (name.equals("")) name = null;
int lowerAge;
if (textField_3.getText().equals("")) lowerAge = -1;
else lowerAge = Integer.parseInt(textField_3.getText());
int upperAge;
if (textField_4.getText().equals("")) upperAge = -1;
else upperAge = Integer.parseInt(textField_4.getText());
getEmployeeDbManager().getData(name, lowerAge, upperAge);
getTableModelOfEmployee().setEmployeeList(getEmployeeDbManager().getEmployeeList());
table.setModel(getTableModelOfEmployee());
table.createDefaultColumnsFromModel();
--------------------------------------------------------

念のために、getButton_1()メソッド全体のソース・コードを提示すると
下記のようになります。

--------------------------------------------------------
private JButton getButton_1() {
   if (button_1 == null) {
      button_1 = new JButton("\u691C\u7D22");
      button_1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            String name = textField_2.getText();
            if (name.equals("")) name = null;
            int lowerAge;
            if (textField_3.getText().equals("")) lowerAge = -1;
            else lowerAge = Integer.parseInt(textField_3.getText());
            int upperAge;
            if (textField_4.getText().equals("")) upperAge = -1;
            else upperAge = Integer.parseInt(textField_4.getText());
            getEmployeeDbManager().getData(name, lowerAge, upperAge);
            getTableModelOfEmployee().setEmployeeList(getEmployeeDbManager().getEmployeeList());
            table.setModel(getTableModelOfEmployee());
            table.createDefaultColumnsFromModel();
         }
      });
   }
   return button_1;
}
--------------------------------------------------------

ここで、

String name = textField_2.getText();

というコードは、氏名のテキスト・フィールドに入力された文字列を
(String型のオブジェクトとして)nameに代入しています。
ここでtextField_2は氏名を入力するためのテキスト・フィールドです。
これは、Designビュー上で該当するテキスト・フィールドをクリック
すれば、Properties欄のVariableという項目に変数名が表示される
ので確認することができます。読者のこれまでの作業手順がこのメール
マガジンに書かれたものと違っていた場合には変数名も異なっている
可能性がありますので、その場合はご自分で修正して下さい。

同様に、上記のソース・コード内のtextField_3は年齢のxx歳から
を示すテキスト・フィールドで、textField_4は年齢のxx歳までを
示すテキスト・フィールドです。これらの変数名も読者によっては
異なっている可能性がありますので、その場合はご自分で修正して
下さい。


その次の行

if (name.equals("")) name = null;

のname.equals("")のequals()メソッドについて説明しておきましょう。
このメソッドはStringクラスのメソッドですが、そのStringオブジェクト
が持っている文字列のデータが引数に指定した文字列(String形のオブ
ジェクト)のデータと等しいかどうかをチェックし、等しければtrueを
等しくなければfalseを返す(boolean型の戻り値を返す)ものです。

つまりname.equals("")は、nameのオブジェクトが持つ文字列データと
""の文字列データ(""は文字列データが空(から)、つまり空文字である
ことを意味する)を比較して等しいかどうかをtrueかfalseかで答えます。

注意しないといけないことは、これは

name == ""

とは意味が違うということです。

==を使った場合、左辺と右辺がオブジェクトの場合はそれらが同一の
インスタンスであるかをチェックするという意味になり、たとえ文字列
データが同じであっても別のインスタンスであればfalseが返ってきま
す。(左辺、右辺がプリミティブ型の場合とは扱いが違うのです。)

したがって、今の場合は==ではなくequals()メソッドを使わなければ
ならないのです。

というわけで、

if (name.equals("")) name = null;

というコードは、氏名のテキスト・フィールドが空文字の場合、つまり
何も入力されなかった場合に、nameをnullにするということを意味しま
す。

で、なんでnameをnullにするかというと、あとでEmployeeDbManagerの
getData()メソッドを呼び出すときにこのnameを第一引数として渡して
いますが、(046号で定義したように)このgetData()メソッドでは、
nameの引数がnullのときにはNAMEカラムの値には関係なくすべての行を
EMPLOYEEテーブルから取り出すようにしているからです。


残りのコードはもう自力で理解できますね。わからないところがあった
ら質問をお寄せください。


ではテストをしてみましょう(H2 Database Engineを起動し、
HumanResourceJFrameを実行してください)。
「検索」のページの「検索」ボタンをクリックすると、JTableに検索結果
のデータが表示されて、データを表示しきれない分は自動的にスクロール・
バーが現れてスクロールできるようになりますね。
(ウインドウが狭くて見づらい場合はウインドウ全体を広げてください。)


では、今回はここまで。


(続く)


では、また来週。



========================================================
◆ 02.文法解説 [演算子]
========================================================

[ビット演算の演算子& | ^]

まずお膳立てのためにビット・パターンについて説明しておき
ましょう。

コンピューターの内部では数は2進数、すなわち0と1だけで表現
されていることはすでに説明しましたね。(もちろん数だけでな
く、すべてのデータがコンピューター内部では0と1だけで表現さ
れているのでしたね。)

044号でお話したように、我々が通常使っている10進数は2進数
に変換すると


10進数  2進数
------  -----
  0         0
  1         1
  2        10
  3        11
  4       100
  5       101
  6       110
  7       111
  8      1000
  9      1001
 10     1010
 11     1011

というようになりますが、たとえば、int型の記憶域の内部では
どのように数が保管されているかというと


10進数      int型の内部表現(2進数)
------  --------------------------------
  0     00000000000000000000000000000000
  1     00000000000000000000000000000001
  2     00000000000000000000000000000010
  3     00000000000000000000000000000011
  4     00000000000000000000000000000100
  5     00000000000000000000000000000101
  6     00000000000000000000000000000110
  7     00000000000000000000000000000111
  8     00000000000000000000000000001000
  9     00000000000000000000000000001001
 10     00000000000000000000000000001010
 11     00000000000000000000000000001011

というようになっています。(頭の空白部分を0でうめて、32桁に
しています。)

この内部表現の各一桁をビット(bit)といいますが、int型は32ビット
(32個のビット)で表現されます。

そして、ビットが並んだものをビット・パターン(bit pattern)と
呼ぶことがあります。

そして、ビットが8個並んだもの(8ビット)をバイト(byte)と呼び
ますから、int型は4バイト(= 4×8ビット = 32ビット)だということ
になります。

このビット・パターンにおいて、一番右側から順番に0ビット目、1ビッ
ト目、2ビット目・・・と呼ぶことがあります。(この呼び方は絶対的な
ものではなく、場合によっては、左側から0ビット目と呼ぶこともあり
ます。)



さて、前回紹介した論理演算子& | ^は、ビット演算の演算子としても
使用されます。

ここでビット演算というのは、各ビットの1をtrue、0をfalseとして扱っ
た論理演算になり、たとえば

1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

という演算になります。
ただし、これらの演算子のオペランドは実際はint型やlong型の整数型に
なり、0ビット目は0ビット目同士、1ビット目は1ビット目同士、2ビット目
は2ビット目同士・・・というように左辺と右辺の同じビットごとに演算が
行われることになります。

たとえば次のようになります。(面倒くさいのでint型を4ビット表現に略す。)

0101 & 0011 = 0001 (=10進数の1)
0101 | 0011 = 0111 (=10進数の7)
0101 ^ 0011 = 0110 (=10進数の6)


これらの演算子の使い方としては、たとえば次のような目的に利用する
ことができます。

・ある決まったビットだけを1にし、他はそのままにする。
・ある決まったビットだけを0にし、他はそのままにする。
・ある決まったビットだけを反転(0なら1に、1なら0に)する。

どうすればこのような目的に利用できるのかは自分で考えてみてください。
わからない人は質問をお寄せください。


(続く)



================================================
◆ 03.演習問題
================================================

上記の演算子の振る舞いを確認するために、下記のようなプログラムを作っ
て実行してみてください。

--------------------------------------------------------
public class BitOperationTest1 {

   public static void main(String[] args) {
      int a = 5;
      int b = 3;
      System.out.println("int a = 5;");
      System.out.println("(bit pattern 0f a = 00000000000000000000000000000101)");
      System.out.println("int b = 3;");
      System.out.println("(bit pattern 0f b = 00000000000000000000000000000011)");
      int c = a & b;
      System.out.println("c = a & b;");
      System.out.println("Result:  c = " + c);
      c = a | b;
      System.out.println("c = a | b;");
      System.out.println("Result:  c = " + c);
      c = a ^ b;
      System.out.println("c = a ^ b;");
      System.out.println("Result:  c = " + c);
   }
}
--------------------------------------------------------



(次回に続く。)


では、また来週。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2011 Future Lifestyle Inc. 不許無断複製