GUI の構成ブロックであるコンポーネントを使用する |
問題: コンテナに含めるコンポーネントの数を増減するにはどうしたらよいか?
- コンポーネントをコンテナに追加するには、Container の
add()
メソッドの 3 つの書式のうちの 1 つを使用する。 コンポーネントを使用するときの一般的なルール に参考情報が記載されている。 コンポーネントをコンテナから取り除くには、Container のremove()
またはremoveAll()
メソッドを使用する。 あるいは、そのコンポーネントを別のコンテナに追加するだけでもよい。こうすれば、そのコンポーネントはそれまでのコンテナから自動的に削除されるからである 。問題: 私のコンポーネントはまったく表示されない!
- コンポーネントをコンテナに追加するときに、コンテナのレイアウトマネージャの適切な
add()
メソッドを使用したか? BorderLayout (ウィンドウのデフォルトのレイアウトマネージャ) は、add()
の引数 1 個のバージョンが呼び出された場合、何のメッセージもなくコンポーネントの追加を失敗させる。add()
メソッドの使用例は、コンテナ内にコンポーネントを配置する レッスンに記載されている。
- デフォルトのレイアウトマネージャを使用していない場合、適切なレイアウトマネージャのインスタンス作成と、コンテナに対する
setLayout()
の呼び出しがうまく行われたか?
- コンポーネントが適切に追加されているとしても、それがすでに可視であったコ ンテナに対して行われていた場合、コンポーネントの追加後に
validate()
をコンテナに対して呼び出したか?
- 作成したコンポーネントが特製のコンポーネント (たとえば Canvas サブクラスなど) の場合、コンポーネントの正しいサイズを返すように
minimumSize()
とpreferredSize()
を実装しているか?
- 非 AWT のレイアウトマネージャを使用しているか、まったくレイアウトマネージャを使用していない場合、そのコンポーネントは正当なサイズをもち、座標を表示しているか?特に、絶対的な位置決めを行っている (レイアウトマネージャを使用しない) 場合は、作成したコンポーネントのサイズを明示的に設定しないと、コンポーネントは表示されない。 レイアウトマネージャを使用しない に参考情報が記載されている。
問題: 特製のコンポーネントが更新されるべきときに更新されない。
- コンポーネントの外観を変化させるたびに、コンポーネントの
repaint()
メソッドが呼び出されているかどうかを確認する。 標準のコンポーネントでは、これは問題ではない。というのも、プラットフォーム仕様のコードがコンポーネントの描画全般を取り仕切るからである。 しかし、特製のコンポーネントでは、コンポーネントの外観を変化させるたびに 、コンポーネントに対して明示的にrepaint()
メソッドを呼び出さなければならない。 そのコンポーネントのコンテナに対してrepaint()
を起動するだけでは十分ではない。 詳細は、キャンバスの使用方法 を参照する。問題: 私のコンポーネントは XYZ イベントを取り込んでいない。
- コンポーネントが他のイベントを取り込んでいるかチェックする。 取り込んでいなければ、たとえば正しいクラスをインスタンス化したコンポーネントなど、正しいコンポーネントを参照しているかどうかを確認する。
- コンポーネントが、あなたが捕らえようとしている種類のイベントを通過させていることを確認する。 たとえば、多くの標準のコンポーネントはマウスイベントを通過させないため、 AWT はそれらの Event オブジェクトを生成することができない。 ACTION_EVENT のような別のイベントタイプ (
action()
メソッドによって処理される ) を代わりに使用することができるか?できない場合は、Canvas サブクラス (または Panel か Applet サブクラス) を実装して、発生したすべてのイベントを調べられるようにする必要がある。問題: 私のアプリケーションは WINDOW_DESTROY イベントを把握できない。このため、私のウィンドウを閉じること (アプリケーションを終了したりその他すべてのことも) ができない!
- Frame サブクラス で、WINDOW_DESTROY イベントに反応するように
handleEvent()
を実装する。 たとえば Panel サブクラスで WINDOW_DESTROY イベントを捕らえられないのは 、コンポーネント階層の上位に Frame があるからである。 終了するにはSystem.exit()
を使用する。 ウィンドウを破棄するには、dispose()
を呼び出すか、単に Frame をhide()
し、再度使用する予定がなければ Frame へのすべての参照が null に設定されていることを確認する。問題: すべての例はアプレットのものだが、このような例をアプリケーションに適用するにはどうしたらよいか?
- この節では、特に注記していないかぎり、Applet クラスのサブクラスは Panel クラスのサブクラスで代用できるし、サブクラスがコンテナとして使用されない場合は、Canvas クラスのサブクラスで代用できる。 一般に、アプレットが何か特別なアプレットの能力 (Applet クラスで定義されたメソッドを使用するなど) に依存していなければ、アプレットをアプリケーションに容易に変換できる。
アプレットをアプリケーションに変換するには、
main()
メソッドを追加する必要がある。このメソッドは、Frame サブクラスのインスタンスを作成し、Applet (または Panel か Canvas) サブクラスのインスタンスを作成し、そのインスタンスを Frame に追加し、その後そのインスタンスのinit()
とstart()
メソッドを呼び出す。 Frame サブクラスは適切な方法で WINDOW_DESTROY イベントを処理するhandleEvent()
を実装しておく。同じ機能を実装するアプレットとアプリケーションの例については、 AnimatorApplet.java と AnimatorApplication.java を参照する。問題: GUI をもつ Java アプリケーションを実行すると、必ず次のような煩わしいエラーメ ッセージが表示される。
Warning: Cannot allocate colormap entry for default background (警告: デフォルトの背景にカラーマップエントリを割り当てることができない)
- このメッセージが表示されるのは Motif システムだけである。 これは、Motif のライブラリが初期化され、GUI のカラーを割り当てるためのスペースがデフォルトのカラーマップにない場合に発生する。 解決策は、デスクトップ上で実行する "カラーマップを大量に消費する" アプリケーションの数を減らすことである。 実行時の Java は、デフォルトのパレットにあるどんなカラーにもそれ自身を適合させるが、Motif ライブラリはこの場合の許容度が低いのである。
読者の抱える問題がこのページに記載されていない場合は、配置に関して起こりやすい問題を参照 し、特製のコンポーネントに関してはグラフィックスに関して起こりやすい問題を参照する。 また、コンポーネントのアーキテクチャの詳細にも、問題解決に役立つことが記載されている。
GUI の構成ブロックであるコンポーネントを使用する |