どうも。阪本です。
なんだかんだで第4回になった、JDK7の新機能。
今回はSwingを触ってみました。
(HTML5が流行る中、Swingはどこまで需要があるのか疑問。。)
さて、そんなSwingに何が追加されたかというと、
「レイヤー」。
ボタンやテキストボックスの上にかぶせるようにレイヤーを配置して、
コンポーネントに重ねて描画できるようになっています。
レイヤーは、コンポーネントを覆いかぶせるJLayerコンポーネントと、
JLayer上に描画を行うJLayerUIの2つのクラスから成ります。
具体的には、以下のように書くことで、
「Start」ボタンをクリックしたら、
表面に半透明でアニメーションを表示することができます。
public class LayerTest { public static void main(String[] args) { JFrame frame = new JFrame("Waiting Animation"); // レイヤーを描画するオブジェクトを生成する final WaitingLayerUI layerUI = new WaitingLayerUI(); JPanel panel = new JPanel(); JButton button = new JButton("Start"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { // 「Start」ボタンをクリックしたら、アニメーションスタート layerUI.start(); } }); panel.add(button, BorderLayout.CENTER); // ボタンが乗ったパネルに、レイヤーを重ねる JLayer<JPanel> layer = new JLayer<JPanel>(panel, layerUI); // レイヤーをフレームに追加する frame.getContentPane().add(layer); frame.setSize(300, 120); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
public class WaitingLayerUI extends LayerUI<JPanel> implements ActionListener { private static final String PROPERTY_NAME = "tick"; private static final int RADIUS = 20; private int rotateCount_ = 0; private boolean running_ = false; @Override public void paint(Graphics g, JComponent c) { super.paint(g, c); if (!this.running_) { // アニメーションを描画しない return; } Dimension size = c.getSize(); Graphics2D g2 = (Graphics2D)g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 全体を半透明な灰色で覆う g2.setPaint(new Color(0, 0, 0, 64)); g2.fillRect(0, 0, size.width, size.height); // 小さな円を円形に表示する(透明度を変化させる) for (int index = 0; index < 12; index++) { double degree = 2 * Math.PI * (index + this.rotateCount_) / 12; int x = (int)(Math.cos(degree) * RADIUS) + size.width / 2; int y = (int)(Math.sin(degree) * RADIUS) + size.height / 2; int alpha = 255 * index / 12; g2.setPaint(new Color(0, 0, 0, alpha)); g2.fillOval(x, y, 8, 8); } // 必ずdisposeする g2.dispose(); } @Override public void actionPerformed(ActionEvent event) { if (this.running_) { // タイマーイベントが発生したら、小さな円の回転位置をずらす this.rotateCount_++; firePropertyChange(PROPERTY_NAME, 0, 1); } } @Override public void applyPropertyChange(PropertyChangeEvent event, JLayer<? extends JPanel> layer) { if (PROPERTY_NAME.equals(event.getPropertyName())) { layer.repaint(); } } public void start() { if (this.running_) { return; } // アニメーションを開始する this.running_ = true; new Timer(50, this).start(); } }
※ここで使っているTimerクラスは、java.util.Timerではなくjavax.swing.Timerです。
このプログラムを実行すると、以下のようになります。
ボタンの上に、簡単に描画を行うことができます。
もちろん、アニメーションではなく単純な描画もOK。
マウスカーソルにくっついてキャラクターが移動するような表示も、
JLayerを使えば簡単にできるようになります。
ではこの辺で。