描画メソッドを使って、更にカスタマイズする
しかし、このJLabelを作成して設定するようなやり方では、表示のカスタマイズといってもやはりやれることに限りがあります。もっと細かに表示を制御したい場合には、どうすればよいのでしょうか。
こうした場合は、描画関係のメソッドをオーバーライドして、表示をグラフィックとして描画するのが一番です。では、先ほどのサンプルを修正して、更に表示をカスタマイズしてみましょう。
package jp.allabout;
import java.awt.*;
import javax.swing.*;
public class SampleApp extends JFrame {
JList list;
public SampleApp(){
this.setSize(new Dimension(300,200));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] items = {"Windows","Linux","Mac OS X","TRON"};
list = new JList(items);
list.setCellRenderer(new MyListCellRenderer());
this.add(list,BorderLayout.CENTER);
}
public static void main(String[] args) {
new SampleApp().setVisible(true);
}
}
class MyListCellRenderer extends JPanel implements ListCellRenderer {
private static final long serialVersionUID = 1L;
private int index;
private String msg;
private boolean isSelected;
@Override
public Component getListCellRendererComponent(
JList list, Object object,int index,
boolean isSelected, boolean hasFocus) {
this.index = index;
this.msg = (String)object;
this.isSelected = isSelected;
this.setMinimumSize(new Dimension(100,22));
this.setPreferredSize(new Dimension(200,22));
return this;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (isSelected){
g.setColor(new Color(255,200,200));
} else {
g.setColor(new Color(200,200,255));
}
g.fillOval(index * 20, 1, 20, 20);
g.setFont(new Font("Serif",Font.BOLD,16));
g.setColor(new Color(0,0,100));
g.drawString(msg, 5, 18);
if (isSelected){
g.setColor(new Color(255,0,0,100));
g.drawRect(0, 0, this.getWidth() - 1, this.getHeight() - 1);
}
}
}
paintComponentをオーバーライドし、更に表示をカスタマイズする。 |
このサンプルでは、項目の並び順に青い円が少しずつ右に移動しながら表示されます。そして項目を選択すると、背景の円が赤に変わり、周囲に赤い枠線が表示されるようになります。
ここでは、MyListCellRendererクラスをJPanelのサブクラスとして定義してあります。そして、getListCellRendererComponentでは「return this」として、インスタンス自身を渡すようにしています。こうすることで、このレンダラークラス自体がそのまま項目の表示用コンポーネントとして使われるようになります。
後は、paintComponentをオーバーライドし、そこで状況に応じた描画を行えばいいわけですね。ここでも、isSelectedの値によって描画する色を変えたり、枠線を描いたりしています。グラフィックを使えば、どんな表示も自由自在というわけです。
レンダラーの基本がわかったところで、次回はJTreeやJTableのレンダラーについても考えてみることにしましょう。