角じゃないコンポーネントを作りたい,の巻
2000.11.28 新規

軽量コンポーネントを使用します。 具体的には、JComponent を親クラスに持つコンポーネント・クラスを作成します。
JComponent のサブ・クラス(=軽量コンポーネント)は、ある程度の透過性を提供されます。 よって色々な形(円など)を形成していても、それ以外の部分(円の外側など)は描画されないので、四角以外のコンポーネントを作成することができます。

また、JFrame などは JComponent を継承していなく、重量コンポーネントと呼ばれています。 こちらは軽量コンポーネントと違って、透過性の提供はされていません。
したがって、(時計アプリで良く見かける)丸いウィンドウなどは残念ながら作成できないようです。

話を戻します。 実際に四角じゃない形を作るには、Graphics や Graphics2D を用います。 描画処理を記述するメソッドは、paint() メソッドではなく paintComponent() メソッドだという点に注意してください。
サンプルでは、描画に Java2D を使用しています。 円の塗りつぶしにグラデーションと半々透明を適用させているので、少し見た目が良くなっています。


「CircleComponent.java」のソースコード
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

/**
 * 丸コンポーネントを表現するクラスです.
 * 
 * @author Musi_chan
 * (Musi_chan@cool.biglobe.ne.jp)
 * @version 2000/11/28 11:12
 */
public class CircleComponent extends JComponent
  implements MouseListener,MouseMotionListener {

/******************************************************************************
  フィールド
******************************************************************************/
  /**
   * マウス・クリック時の座標のインスタンス変数です.
   */
  private Point pressedPoint;
  /**
   * 自身を描画するための円のインスタンス変数です.
   */
  private Ellipse2D.Double circle;
  /**
   * グラデーションのインスタンス変数です.
   */
  private GradientPaint gradient;
  /**
   * 透明度のインスタンス変数です.
   */
  private Composite comp;

/******************************************************************************
  コンストラクタ
******************************************************************************/
  /**
   * コンストラクタです.
   */
  public CircleComponent() {
    // 親クラスのコンストラクタ呼び出し
    super();
    // マウス・イベント・リスナの登録
    addMouseListener(this);
    addMouseMotionListener(this);

    // インスタンス変数の初期化
    pressedPoint=null;
    circle=null;
    gradient=null;
    comp=null;
  }

/******************************************************************************
  メソッド
******************************************************************************/

/******************************************************************************
  ビュー
******************************************************************************/
  /**
   * 背景を描画するメソッドです.
   * 
   * @param g グラフィックス
   */
  protected void paintComponent(Graphics g) {
    // 親クラスのメソッドを呼び出し
    super.paintComponent(g);

    // 描画時に使用する円の生成
    circle=new Ellipse2D.Double(0,0,getWidth(),getHeight());
    // 描画時に使用するグラデーションの生成
    gradient=new GradientPaint(0,0,getBackground()
      ,getWidth(),getHeight(),Color.white,true);
    // 描画時に使用する透明度の生成
    comp=AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.75F);

    // 描画用グラフィックスの取得
    Graphics2D g2d=(Graphics2D)g;
    // グラデーション設定
    g2d.setPaint(gradient);
    // 透明度設定
    g2d.setComposite(comp);
    // 円の描画(塗りつぶし)
    g2d.fill(circle);
  }

/******************************************************************************
  コントローラ
******************************************************************************/
  /**
   * マウス・イベント用メソッドです.
   * コンポーネント上でマウス・ボタンが押されると呼び出されます.
   * 
   * @param me マウス・イベント
   */
  public void mousePressed(MouseEvent me) {
    // 押されたときのマウス座標を取得
    pressedPoint=new Point(me.getX(),me.getY());
    // 自身の円の範囲に入っているか判定
    if(circle!=null&&!circle.contains(pressedPoint)) {
      pressedPoint=null;
    }
  }

  /**
   * マウス・イベント用メソッドです.
   * コンポーネント上でマウス・ボタンが離されると呼び出されます.
   * 
   * @param me マウス・イベント
   */
  public void mouseReleased(MouseEvent me) {
    pressedPoint=null;
  }

  /**
   * マウス・イベント用メソッドです.
   * コンポーネント上でマウス・ボタンがクリックされると呼び出されます.
   * 
   * @param me マウス・イベント
   */
  public void mouseClicked(MouseEvent me) {
  }

  /**
   * マウス・イベント用メソッドです.
   * コンポーネント上にマウスが入ると呼び出されます.
   * 
   * @param me マウス・イベント
   */
  public void mouseEntered(MouseEvent me) {
  }

  /**
   * マウス・イベント用メソッドです.
   * コンポーネント上からマウスが出ると呼び出されます.
   * 
   * @param me マウス・イベント
   */
  public void mouseExited(MouseEvent me) {
  }

  /**
   * マウス・モーション・イベント用メソッドです.
   * コンポーネント上でドラッグされると呼び出されます.
   * 
   * @param me マウス・イベント
   */
  public void mouseDragged(MouseEvent me) {
    // 自身の円の範囲でドラッグされているか判定
    if(pressedPoint!=null) {
      // 座標の取得
      Point location=getLocation();
      // 座標の増減計算
      location.x+=me.getX()-pressedPoint.x;
      location.y+=me.getY()-pressedPoint.y;
      // 座標の設定
      setLocation(location);
    }
  }

  /**
   * マウス・モーション・イベント用メソッドです.
   * コンポーネント上でマウスが動くと呼び出されます.
   * 
   * @param me マウス・イベント
   */
  public void mouseMoved(MouseEvent me) {
  }
}


「SampleDragFrame.java」のソースコード
import java.awt.*;
import javax.swing.*;

/**
 * ドラッグのサンプル・プログラムです.
 * 
 * @author Musi_chan
 * (Musi_chan@cool.biglobe.ne.jp)
 * @version 2000/11/28 10:53
 */
public class SampleDragFrame extends JFrame {
/******************************************************************************
  フィールド
******************************************************************************/
  /**
   * メイン・パネルのインスタンス変数です.
   */
  private JPanel routePanel;
  /**
   * 丸コンポーネント群のインスタンス変数です.
   */
  private CircleComponent[] cCompo;

/******************************************************************************
  コンストラクタ
******************************************************************************/
  /**
   * コンストラクタです.
   */
  public SampleDragFrame() {
    this("");
  }

  /**
   * コンストラクタです.
   * 
   * @param args 起動時の引数(ルック&フィール名)
   */
  public SampleDragFrame(String args) {
    // ルック&フィール名保持用ローカル変数
    String LAFName;

    // 各種ウィンドウ設定
    setLocation(50,25);
    setSize(320,340);
    setResizable(true);
    setTitle("Drag sample program.");
    getContentPane().setLayout(new BorderLayout());
    //setIconImage(ICON.getImage());
    setBackground(SystemColor.menu);
    setForeground(SystemColor.menuText);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    // ルック&フィール名の判別
    if(args.equals("windows")) {
      LAFName="com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
    } else if(args.equals("motif")) {
      LAFName="com.sun.java.swing.plaf.motif.MotifLookAndFeel";
    } else {
      LAFName="javax.swing.plaf.metal.MetalLookAndFeel";
    }
    // ルック&フィール設定
    try {
      UIManager.setLookAndFeel(LAFName);
    } catch(ClassNotFoundException cnfe) {
    } catch(InstantiationException ie) {
    } catch(IllegalAccessException iae) {
    } catch(UnsupportedLookAndFeelException ulafe) {
    }

    // メイン・パネルの設定と追加
    setRoutePanel();
    getContentPane().add(routePanel,BorderLayout.CENTER);

    // メイン・ウィンドウの表示
    setVisible(true);
  }

/******************************************************************************
  メソッド
******************************************************************************/

/******************************************************************************
  ビュー
******************************************************************************/
  /**
   * メイン・パネルの設定をするメソッドです.
   */
  private void setRoutePanel() {
    // メイン・パネルのインスタンス生成
    routePanel=new JPanel();
    // メイン・パネルのレイアウト等設定
    routePanel.setLayout(null);
    routePanel.setBackground(Color.white);

    // 使用カラー配列の定義
    Color[] c={Color.red,Color.green,Color.blue
      ,Color.cyan,Color.magenta,Color.yellow
      ,Color.gray,Color.orange,Color.pink};
    // 丸コンポーネント配列の生成
    cCompo=new CircleComponent[c.length];
    for(int i=0;i<c.length;i++) {
      // 丸コンポーネントのインスタンス生成
      cCompo[i]=new CircleComponent();
      // 丸コンポーネントの配置
      cCompo[i].setBounds((i%3)*100,(i/3)*100,100,100);
      // 丸コンポーネントの背景設定
      cCompo[i].setBackground(c[i]);
      // メイン・パネルへの追加
      routePanel.add(cCompo[i]);
    }
  }

/******************************************************************************
  コントローラ
******************************************************************************/
  /**
   * メインメソッドです.起動時に呼び出されます.
   * 
   * @param args コマンドライン引数
   */
  public static void main(String[] args) {
    if(args.length==0) {
      new SampleDragFrame();
    } else {
      new SampleDragFrame(args[0]);
    }
  }
}

戻る