MDI タイプのアプリで壁紙を張りたい,の巻
2000.12.14 新規
2000.12.19 修正

基本部分は JDesktopPane クラスの機能を利用します。 なので、MDI アプリ自体の作成方法等は他のドキュメントを参照してください。

基本方針は、単独で使用できること、です。 つまり、壁紙として使用するイメージの読込みも自身で行い、完全に読み込んだ状態まで動作待ちをして、自身(コンポーネント)の背景に描画する、ことを行います。 また、オマケの機能として、「中央に表示」「並べて表示」「拡大」という3種類の描画方法も提供できるようにしてみました。

ポイントは

といったところです。
イメージを読込む際、JAR による圧縮されたイメージにも対応できるように、二段階のロード方法を取っています。 始めに、与えられた文字列(イメージのパス名)からイメージをロードしに行き、取得できれば結果を返します。 取得に失敗した場合には、引き続いて、文字列から URL に変換を行います。 この URL 変換により、JAR 圧縮ファイル内のイメージも読込むことが可能になります。 どちらの方法にも失敗した場合には null を返し、画像の描画を行わないようにします。

ロードまでのブロック動作は、MediaTracker の機能を用いています。 こうしておかないと、いざ描画するときになってからイメージをロードしに行くので、大きい壁紙を張ろうとした場合に格好悪くなってしまいます。
MediaTracker 自体の簡単な使い方は、次のようになります。

この「ロード完了チェック」のとき、実際のロードを開始しています。

描画方法の選択は、ほんのオマケ機能ですが、ユーザにとって嬉しい機能・ほぼ必須の(なければ要求される)機能でもあります。 この3種類の方法はクラス変数を用意して、それから選べるようにしています。

壁紙の動的な変更については、update() メソッドをオーバ・ライドすることで行っています。 背景画像と描画方法をアクセス・メソッドで設定変更したあとに repaint() メソッドを呼び出すことで、実際に壁紙が変更されます。

repaint() → update() → paintComponent()
という流れで、描画メソッドが呼ばれます。
下のソースコードでは、描画方法が変更された時点で再描画を行うようにしています。


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

/**
 * 壁紙機能を持った仮想デスク・トップを提供するクラスです.
 * 
 * @author Musi_chan
 * (Musi_chan@cool.biglobe.ne.jp)
 * @version 2000/12/14 10:38
 */

public class WallPaperDesktopPane extends JDesktopPane {
/******************************************************************************
  フィールド
******************************************************************************/
  /**
   * 背景画像保持用インスタンス変数
   */
  private Image bgImage;
  /**
   * 画像読込みのためのメディア・トラッカ保持用インスタンス変数
   */
  private MediaTracker tracker;
  /**
   * 描画方法保持用インスタンス変数
   */
  private int drawingMethod;

  /**
   * 描画方法を決定するためのクラス変数
   */
  public static final int DRAWING_METHOD_CENTER=0;
  /**
   * 描画方法を決定するためのクラス変数
   */
  public static final int DRAWING_METHOD_TILE=1;
  /**
   * 描画方法を決定するためのクラス変数
   */
  public static final int DRAWING_METHOD_RESIZE=2;

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

  /**
   * コンストラクタです.
   * 
   * @param imageName 背景画像名
   */
  public WallPaperDesktopPane(String imageName) {
    this(imageName,DRAWING_METHOD_CENTER);
  }

  /**
   * コンストラクタです.
   * 
   * @param imageName 背景画像名
   * @param drawingMethod 描画方法
   */
  public WallPaperDesktopPane(String imageName,int drawingMethod) {
    super();

    // 背景画像の取得
    setImage(imageName);
    // 描画方法の決定
    this.drawingMethod=drawingMethod;
  }

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

    // 画像サイズ保持用ローカル変数
    Dimension imgSize;

    // イメージの判定
    if(bgImage==null) {
      return;
    }

    // 画像のサイズ取得
    imgSize=new Dimension(bgImage.getWidth(this),bgImage.getHeight(this));
    // 背景画像の描画各種
    if(drawingMethod==DRAWING_METHOD_CENTER) {
      // コンポーネントとイメージのサイズを比較
      int x=(getSize().width-imgSize.width)/2;
      int y=(getSize().height-imgSize.height)/2;
      // 比較結果から真中に描画
      g.drawImage(bgImage,x,y,this);
    } else if(drawingMethod==DRAWING_METHOD_TILE) {
      // タイルのように敷き詰めて描画
      for(int y=0;y<getSize().height;y+=imgSize.height) {
        for(int x=0;x<getSize().width;x+=imgSize.width) {
          g.drawImage(bgImage,x,y,this);
        }
      }
    } else if(drawingMethod==DRAWING_METHOD_RESIZE) {
      // 拡大(縮小)して描画
      g.drawImage(bgImage,0,0,getSize().width,getSize().height,this);
    }
  }

  /**
   * 背景等を再描画するメソッドです.
   * 
   * @param g グラフィックス
   */
  public void update(Graphics g) {
    paintComponent(g);
    paint(g);
  }

  /**
   * イメージを設定するクラスメソッドです.
   * 
   * @param imageName 設定するイメージのファイル名
   */
  public void setImage(String imageName) {
    // メディア・トラッカの生成
    tracker=new MediaTracker(this);
    // 背景画像の取得
    bgImage=getImageFromURL(imageName);
    // メディア・トラッカへ画像の追加
    tracker.addImage(bgImage,0);

    // メディア・トラッカによる,画像読込みの待ち
    tracker.checkAll(true);
    try {
      tracker.waitForAll();
    } catch (InterruptedException e) {
      bgImage=null;
    }
  }

  /**
   * ファイル名からイメージを取得するクラスメソッドです.
   * 
   * @param imageName 取得するイメージのファイル名
   * @return 取得したイメージ
   */
  private Image getImageFromURL(String imageName) {
    // イメージ保持用ローカル変数
    Image image;
    // イメージが存在するURL保持用ローカル変数
    URL url;

    // イメージのURLを取得
    try {
      url=getClass().getResource(imageName);
    } catch(Exception e) {
      url=null;
    }

    // URLからイメージを取得
    image=null;
    try {
      if(url==null) {
        image=Toolkit.getDefaultToolkit().getImage(imageName);
      } else {
        image=Toolkit.getDefaultToolkit().getImage(url);
      }
    } catch(ExceptionInInitializerError eiie) {
    } catch(LinkageError le) {
    }

    return image;
  }

  /**
   * イメージを設定するクラスメソッドです.
   * 
   * @param image 取得するイメージ
   */
  public void setImage(Image image) {
    bgImage=image;
  }

  /**
   * イメージを取得するクラスメソッドです.
   * 
   * @return イメージ
   */
  public Image getImage() {
    return bgImage;
  }

  /**
   * 描画方法を設定するメソッドです.
   * 
   * @param drawingMethod 描画方法
   */
  public void setDrawingMethod(int drawingMethod) {
    // 描画方法の決定
    this.drawingMethod=drawingMethod;
    repaint();
  }

  /**
   * 描画方法を取得するメソッドです.
   * 
   * @return 描画方法
   */
  public int getDrawingMethod() {
    return drawingMethod;
  }
}

戻る