Index > プルダウンメニューつきのボタンの自作(Java Swing)
Fri, April 7, 2006

プルダウンメニューつきのボタンの自作(Java Swing)

Eclipseの[Run]ボタンのようにプルダウンメニュー付きのボタンを自作してみました。

概要

Eclipseの[Run]ボタンは次のようになっています。

これと同じ機能のボタンをswingを使って自作してみます。

完成イメージ(最終版)

Step1 プルダウンなしのボタンをつくる

まずは、プルダウン機能なしのボタンを作成します。

完成したボタン(その1)

コード Button1.java

import javax.swing.*;

public class Button1 extends JButton{
    public Button1(){
        super();
        setIcon(new TriangleIcon());
        setFocusPainted(false);
    }
}

コード TriangleIcon.java

import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;

import javax.swing.*;

public class TriangleIcon extends ImageIcon{

    public TriangleIcon(){
        super();

        int w=24;
        int h=24;
        BufferedImage bimg=createImage(new Dimension(w,h));

        Graphics2D g2=(Graphics2D)bimg.getGraphics();

        //Green Circle
        g2.setColor(Color.GREEN);
        Ellipse2D e=new Ellipse2D.Float(0,0,w-1,h-1);
        g2.fill(e);

        //Paint Border
        g2.setColor(Color.BLACK);
        g2.draw(e);

        //White Triangle
        g2.setColor(Color.WHITE);
        Polygon pol=new Polygon();
        pol.addPoint(7,5);
        pol.addPoint(7,h-5);
        pol.addPoint(w-5,h/2);
        g2.fill(pol);

        g2.dispose();

        setImage(bimg);

    }
    static private BufferedImage createImage(Dimension size){
        BufferedImage bimg=
            new BufferedImage(size.width,size.height,BufferedImage.TYPE_4BYTE_ABGR);
        {
            Graphics g=bimg.getGraphics();
            g.setColor(new Color(0x00FFFFFF,true));
            g.fillRect(0,0,size.width,size.height);
            g.dispose();
        }
        return bimg;
    }
}

ボタンイメージは、 イラストレータなどの画像作成ツールで イメージデータとして作成しても 構いませんが、今回はImageIconを継承して プログラム内でボタンイメージを直接描画しています。

Step2 プルダウン用の下三角ボタンを追加

プルダウンメニューを起動させるための下三角ボタンを どう実装するか、というのは考えどころですが、 ここでは、SwingのBorderを使って描画しています。

jEditのソースコードからアイデアを拝借しました。

完成したボタン(その2)

コード Button2.java

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

public class Button2 extends JButton{

    public Button2(){
        super();
        setIcon(new TriangleIcon());
        setFocusPainted(false);

        Border border=BorderFactory.createEtchedBorder();
        setBorder(BorderFactory.createCompoundBorder(border,new PullDownBorder()));
    }
    static class PullDownBorder extends AbstractBorder {
        static final int WIDTH = 16;

        public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
            g.translate(x+w-WIDTH,y-1);

            // down arrow
            int w2 = WIDTH/2;
            int h2 = h/2;
            g.setColor(Color.black);

            g.drawLine(w2-5,h2-2,w2+4,h2-2);
            g.drawLine(w2-4,h2-1,w2+3,h2-1);
            g.drawLine(w2-3,h2  ,w2+2,h2  );
            g.drawLine(w2-2,h2+1,w2+1,h2+1);
            g.drawLine(w2-1,h2+2,w2  ,h2+2);

            g.translate(-(x+w-WIDTH),-(y-1));
        }

        public Insets getBorderInsets(Component c){
            return new Insets(0,0,0,WIDTH);
        }
    }
}

Step3 下三角ボタン領域をクリックしたときにプルダウンメニューが出る振る舞いを追加

Borderとして実装した下三角描画領域部分のクリックイベントを キャッチするために processMouseEvent をオーバライドします。

完成したボタン(最終版)

コード Button3.java

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class Button3 extends Button2{
    public Button3(){
        super();
        enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    }

    protected void processMouseEvent(MouseEvent evt){
        if(isEnabled()==false){
            return;
        }

        switch(evt.getID()) {
            case MouseEvent.MOUSE_PRESSED:
                Border border = getBorder();
                Insets insets = border.getBorderInsets(Button3.this);

                if(evt.getX() >= getWidth() - insets.right) {
                    showPopupMenu(0,getHeight());
                }
                else{
                    super.processMouseEvent(evt);
                }

                break;

            case MouseEvent.MOUSE_EXITED:
                setCursor(Cursor.getDefaultCursor());
                super.processMouseEvent(evt);
                break;

            default:
                super.processMouseEvent(evt);
                break;
        }
    }
    private void showPopupMenu(int x,int y){
        JPopupMenu popup=new JPopupMenu();
        popup.add(new JMenuItem("item1"));
        popup.add(new JMenuItem("item2"));
        popup.add(new JMenuItem("item3"));
        popup.show(this,x,y);
    }
}
 Twitter
follow me on Twitter
 Categories