9.4 ルートペイン
9.4.1 すべての親コンテナ
Swing の GUI アプリケーションで重量コンテナとして表示されるウィンドウは、必ずルートペインと呼ばれる軽量コンテナを内部に保有しています。Swing アーキテクチャをサポートしている重量コンテナは JFrame, JDialog, JWindow, JApplet など、これまで使ってきたウィンドウです。これらのクラスは、以前説明したように、必ず RootPaneContainer インタフェースを実装しています。
RootPaneContainer インタフェースで宣言されている getRootPane() メソッドから、重量コンテナが保有するルートペインを得ることができます。Swing アーキテクチャの大きな特徴は、このルートペインの存在です。重量ウィンドウは子コンポーネントにルートペインを管理し、このルートペインはウィンドウの作業領域全体を一元管理してくれるコンポーネントの総合商社となります。
私たちがこれまで、getContentPane() メソッドから得たコンテンツペインにコンポーネントを追加してきましたが、このコンテンツペインもルートペインに管理されるコンテナです。ルートペインはコンテンツペインを管理するだけではなく、メニューバーなども管理します。
ルートペインである javax.swing.JRootPane クラスは、独立したインスタンスを生成することもできますが、通常はウィンドウを生成すると同時に作られるデフォルトのルートペインを使うことになるでしょう。
java.lang.Object | +--java.awt.Component | +--java.awt.Container | +--javax.swing.JComponent | +--javax.swing.JRootPane
public class JRootPane extends JComponent implements Accessible
最終的に、あらゆる Swing 軽量コンポーネントはルートペインに集約されると考えることができます。ルートペインは一般的な軽量コンポーネントを管理するコンテンツペインと、作業領域に表示するメニューバー、最前面に表示するガラスペインなどを内部で管理しています。
コンストラクタ | 解説 |
---|---|
public JRootPane() | JRootPane を作成します。 |
メソッド | |
public void setJMenuBar(JMenuBar menu) | レイヤーペインで使用されるメニューバーを追加または変更する。 |
public JMenuBar getJMenuBar() | レイヤーペインからメニューバーを返す。 |
public void setContentPane(Container content) | コンテンツペインを設定する。 |
public Container getContentPane() | コンテンツペインを返す。 |
public void setLayeredPane(JLayeredPane layered) | レイヤーペインを設定する。 |
public JLayeredPane getLayeredPane() | レイヤーペインを返す。 |
public void setGlassPane(Component glass) | ガラスペインを設定する。 |
public Component getGlassPane() | ガラスペインを返す。 |
表1は JRootPane クラスのコンストラクタと、ルートペインが内部で管理している子コンポーネントへのアクセッサメソッドを示しています。ルートペインの直接の子には、ガラスペインとレイヤーペインが存在しています。
ガラスペインは、あらゆるコンポーネントの手前に存在するコンポーネントです。デフォルトでは透明なので何も影響を与えませんが、ガラスペインで何らかの図を描画すると、常にあらゆるコンポーネントの前面に表示されるでしょう。レイヤーペインについてはすぐ後で詳しく解説しますが、レイヤーペインはコンポーネントの階層を制御するためのコンテナで、このレイヤーペインによってメニューバーとコンテンツペインが管理されています。RootPaneContainer インタフェースからも、ガラスペインやレイヤーペインにアクセスできます。
メニューバーについては第10章で解説しますが、Swing ではメニューバーも軽量コンポーネントに属しているため、自由にコンテナに追加することができます。しかし、一般的なデザインでメニューバーを正しく表示するには、ルートペインにメニューバーを設定します。
通常、一般的な開発でアプリケーションプログラマが JRootPane クラスを拡張したり、インスタンスを生成する必要はありません。しかし、JRootPane クラスから、内部で管理されているガラスペインやレイヤーペインにアクセスできるという事実は極めて重要です。特に、すべてのコンポーネントの前面に表示することができるガラスペインは最も興味深い存在でしょう。
RootPaneContainer インタフェースや JRootPane クラスからガラスペインを設定することもできるため、独自のコンポーネントをガラスペインとして設定することで、最前面に何らかの図を表示することができます。
import java.awt.*; import javax.swing.*; public class Test { public static void main(String args[]) { JLabel label = new JLabel(new ImageIcon("icon1.jpg")); JButton button = new JButton("I love Kitty!!"); JTextArea text = new JTextArea(10 , 30); JFrame win = new JFrame(); win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); win.setBounds(10 , 10 , 400 , 300); win.getContentPane().setLayout(new FlowLayout()); win.getContentPane().add(label); win.getContentPane().add(button); win.getContentPane().add(text); win.setGlassPane(new NetGlassPane()); win.getGlassPane().setVisible(true); win.show(); } } class NetGlassPane extends JComponent { public void paintComponent(Graphics g) { for(int i = 0 ; i < getWidth() ; i += 10) g.drawLine(i , 0 , i , getHeight()); for(int i = 0 ; i < getHeight() ; i += 10) g.drawLine(0 , i , getWidth() , i); } }
コード1は、コンポーネント上にクロスするラインを描画する NetGlassPane クラスを定義し、これをガラスペインとしてウィンドウに設定しています。ガラスペインはデフォルトで不可視となっているため setVisible() メソッドを使って可視状態にすると、実行結果のように、あらゆるコンポーネントの全面に表示されます。通常、ガラスペインは図のように透明の軽量コンポーネント上に背景を透過しながら何らかの図や文字を描画します。
コンテンツペインはガラスペインよりも階層が下なので、このプログラムではボタンやラベル、テキストコンポーネントを追加していますが、ガラスペインに上書きされていることが確認できます。ガラスペインは、このようにあらゆるコンポーネントの全面に描画されるため、ドラッグ処理などの演出に活用することができるでしょう。