Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

Java SE 7(JDK7)の見どころをまとめてみました!(その4)

どうも。阪本です。

なんだかんだで第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を使えば簡単にできるようになります。


ではこの辺で。