JTabbedPaneのタブの選択時の背景色を設定する
1990年代にサンマイクロシステムズ社が開発したオーク言語を改名してできたJava。JavaアプリケーションでJTabbedPaneを使ったときの応用技術を紹介します。
Javaでごく普通にJTabbedPaneを使用すると、タブの選択時の色はグレーになります。また、他のSwingベースのコンポーネントも基本はグレーのため、基本的にシステム全体がグレーで構成されます。
複数のタブがあるJTabbedPaneの場合、通常はどのタブもグレーで表示されるため判別しにくいと思うことがあります。タブごとに選択時の色を設定することができれば、ユーザにとってよりわかりやすい画面になると考えられます。
そこで、ユーザにタブの中身で画面を判別してもらうのではなく、タブの色で視覚的に判断できるようにする方法を考えました。
JTabbedPaneのタブ選択時の背景色設定をする(UIManagerを使う)
JTabbedPaneのタブの背景色を変更する方法として、UIManagerを使う方法があります。それを実装するためには、下記コードを記述します。
※(Color.BLUEの部分は、適宜指定したい色とします。)
上記コードを含むアプリケーションを実行すると、以下の図のようになります。
上の図のようにタブの選択時の背景色は、設定されています。
しかし、この方法では以下の問題点があります
1)システム全体で変更されてしまう
2)タブごとに背景色を変更することができない
JTabbedPaneのタブ選択時の背景色設定をする(UIManagerを使わない)
UIManagerを使用する方法では、問題点が2点ありました。
その問題を解決策として、次のように考えました。
-> タブを追加するときには、コンポーネントを指定する
-> コンポーネントを追加するときに、色を指定する
-> どのコンポーネントが追加されたときに、どの色を指定されたかを関連付ける
これを実現方法を以下に記述します。
1)色を指定するためのメソッドを追加する
JTabbedPaneで、コンポーネントを追加するメソッドとして以下のものがあります。
add(Component component, int index)
add(Component component, Object constraints)
add(Component component, Object constraints, int index)
add(String title, Component component)
addTab(String title, Component component)
addTab(String title, Icon icon, Component component)
addTab(String title, Icon icon, Component component, String tip)
insertTab(String title, Icon icon, Component component, String tip, int index)
これらは、すべてTabの中に追加するコンポーネントを指定しています。
そこで、これらのメソッドにColorを指定するようにします。
addTab(String title, Icon icon, Component component, String tip, Color color )
addTab(String title, Component component, Color color )
add( Component component, Color color )
add( String title, Component component, Color color )
add( Component component, int index, Color color )
add( Component component, Object contains, Color color )
add( Component component, Object contains, int index, Color color)
2)コンポーネントと色の関連付けを保持する
1)にて追加したメソッドの中で、コンポーネントと色の関連付けをMapというコレクションクラスを使って実現します。そのために、生成したMapオブジェクトのputメソッドを使って関連付けを行います。
Map#put(Object key, Object value) で第一引数のkey部分にComponent、第二引数のvalue部分をColorを指定します。
3)タブが削除されたときに対応する
タブを削除するメソッドが呼ばれた際に、Mapから関連するColorオブジェクトを削除することも必要です。削除対象のコンポーネントをキーにして、関連したColorオブジェクトをMapから削除します。
そのために下記のメソッドをオーバーライドします。
removeTabAt( int index )
remove(Component component)
removeAll()
コンポーネントと色の関連付けを画面に反映させる
タブ内に表示するコンポーネントと色の関連付けを画面に反映させると下記のような画面なります。

上記のような画面を実現するために、TabbedPaneUIクラスを新たにJTabbedPaneを継承したクラスの内部クラスとして作成します。
今回の例では、MetalTabbedPaneUIを継承して作成しています。
MetalTabbedPaneUIクラスのpaintTabBackgroundメソッドをオーバーライドします。
int x, int y, int w, int h, boolean isSelected ) {
//描画対象のタブに登録されているコンポーネントを取得する
Component c = getComponentAt( tabIndex );
if ( c == null ) {
selectColor = null;
super.paintTabBackground( g, tabPlacement, tabIndex,
x, y, w, h, isSelected );
return;
}
//コンポーネントをキーに、選択時の色を取得する
Object obj = selectedColorMap.get( c );
if ( obj instanceof Color ) {
selectColor = (isSelected?(Color)obj:null);//JTabbedPaneのメンバー変数に選択されているときの色を設定する
super.paintTabBackground( g, tabPlacement, tabIndex, x, y, w, h, isSelected );
return;
}
//デフォルト色を使用(選択時の色が指定されていない場合)
selectColor = tabAreaBackground;
super.paintTabBackground( g, tabPlacement, tabIndex, x, y, w, h, isSelected );
}
まとめ
長々と書いてきましたが、実現したいことはただ一つ「ユーザがタブの色で視覚的に判断できるようにする」ということです。
JTabbedPaneのサブクラスで上記の実装を行い、使用することで画面全体がグレーではなく、色付きの画面にすることができると思います。画面全体が同じような色で構成されていることは、小さい画面で少ないコンポーネントを使用するアプリケーションであれば、それほど気になりません。
しかし、いろいろなコンポーネントを組み合わせて作られている画面では、同じような色だけで構成されていると視覚的に目的の画面を見つけることは難しくなります。その点を打開するために、このコラムの内容を生かしていただけると幸いです。
長い文面となってしまいましたが、最後まで読んでいただきありがとうございました。

