Android で再開する Java プログラミング(2) - 図形の描画
Google の携帯端末プラットフォーム Android をきっかけに、Java プログラミングを再開しようという連載になっています。Java の文法を一通り知っている人を対象にして、Android 上で動く Java アプリを作っていきます。Android のSDKには、出来の良いエミュレータが用意されています。そのため日本国内で Android 端末が発売されていない現状でも作ったアプリをエミューレータ上で動かして楽しむことができます。来るべき、Android に備えて Java プログラミングを始めておきましょう。
本連載で作るもの
- Android 上で動作する自作ソフト(予定)
- モグラ叩き
- 迷路ゲーム
- チャット
- SQLiteを利用したメモ帳
対象とする読者
- Android で自作ツールを作ってみたい人
- Java で何か作ってみたい人
- Java の文法を一通り知っている人
グラフィックの描画
さて、前回は、Android の開発環境をセットアップしましたので、今回は、楽しくグラフィック機能を使って、お絵かきしてみようと思います。
一番簡単に、画面に円を描くだけのプログラムを作ってみたいと思います。(前回手順で Eclipse がインストールしてあるものとして解説していきます。)
(1)ファイルメニューから新規プロジェクト作成
Eclipseのメインメニューより、[File > New > Project…]をクリックします。
(2)Android プロジェクトを選択
「Select a wizard」ダイアログが出るので、「Android」のグループから「Android Project」を選択して、[Next]をクリックします。
(3)プロジェクトの情報を入力
プロジェクト名やプロパティなどを入力する画面になります。次のように情報を入力します。
| 項目 | 設定する値 |
|---|---|
| Project name | TestCircle |
| Package name | com.example.android.circle |
| Activity name | TestCircle |
| Application name | TestCircle |
入力したら、[Finish]ボタンをクリックします。
(4)メインファイルを開く
以上の作業で、Android アプリケーションの雛型が作成されています。メインファイルを開いてみましょう。画面左側に出ている「Project Explorer」にて、「src」のフォルダの中にある「com.example.android.circle」>「TestCircle.java」をダブルクリックします。(もし、Project Explorerが表示されていない場合には、メニューより、[Window > Show View > Project Explorer]をクリックします。)
(5)ソースファイルの書き換え
メインファイルの TestCircle.java を開いたら、ソースコードを以下のように書きかえます。ここでは、プロジェクト作成の手順だけを説明するので、詳しい解説は、後で説明します。
package com.example.android.circle;
import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.os.Bundle;
import android.view.View;
// メインクラス
public class TestCircle extends Activity {
/** Activityが生成された時に呼ばれる */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// View クラスのインスタンスを生成する
MyCircleView view = new MyCircleView(getApplication());
// View に設定する
setContentView(view);
}
}
// 表示用のクラス
class MyCircleView extends View {
// View の初期化
public MyCircleView(Context context) {
super(context);
setFocusable(true);
}
// 実際に描画を行うメソッド
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 背景色の設定
canvas.drawColor(Color.WHITE);
// 描画オブジェクトの生成
Paint paint = new Paint();
paint.setAntiAlias(true);
// 円を描画する
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
canvas.drawCircle(150, 150, 100, paint);
}
}
(6)デバッグの設定を行う
デバッグボタンの右にある▼をクリックして、ポップアップメニューから[Debug Configurations…]を選んでクリックします。
(7)デバッグ設定を作成する
デバッグ設定のダイアログが出るので、画面左から[Android Application]をダブルクリックします。Android 用の設定が生成されるので、Project で、[TestCircle]を選択します。そして、[Apply]ボタンをクリックします。最後に、[Debug]ボタンをクリックするとエミュレータが実行されます。
(8)ロック解除して実行を待つ
エミュレータの初回起動では、Android のロゴが出た後に、画面がロックされてしまいうので、エミュレータの[MENU]ボタンをクリックします。すると、アプリケーションが実行されます。
(9)実行画面を確認
プログラムが実行されたら、画面を確認します。今回のプログラムは、画面に青色の円が描画されます。
プログラムについて
それでは、具体的にプログラムの内容を確認していきましょう。と言っても、大部分は定型的なものです。Android のアプリケーションが実行されると、メインクラス(Activity)の、onCreate() メソッドが呼び出されます。
この onCreate() メソッドでは、どのような描画を行うのか、View の設定を行います。ここでは、MyCircleView という View クラスを生成し設定しています。MyCircleView は、この後定義します。
public class TestCircle extends Activity {
/** Activityが生成された時に呼ばれる */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// View クラスのインスタンスを生成する
MyCircleView view = new MyCircleView(getApplication());
// View に設定する
setContentView(view);
}
}
MyCircleView は、Android の View クラスを継承したものとなっています。Viewクラスは、ゲーム画面や独自にカスタマイズされた画面を作成する場合に利用します。キーの押下やタッチパネルのイベントを利用することができます。
class MyCircleView extends View {
// View の初期化
public MyCircleView(Context context) {
super(context);
setFocusable(true);
}
...
そして、いよいよ画面への描画を行うのですが、画面の描画は、onDraw() メソッドの中で行うことになっています。この onDraw() メソッドは、View の処理の中で、描画が行われるタイミングごとに呼び出される仕組みになっているのです。
...
// 実際に描画を行うメソッド
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 背景色の設定
canvas.drawColor(Color.WHITE);
// 描画オブジェクトの生成
Paint paint = new Paint();
paint.setAntiAlias(true);
// 円を描画する
paint.setStyle(Paint.Style.FILL); // 塗りつぶしを指定
paint.setColor(Color.BLUE); // 色は青色で
canvas.drawCircle(150, 150, 100, paint);
}
...
実際に、円を描画する際には、Paint のインスタンスを作っておきます。この Paint クラスは、描画色や塗りつぶしの設定を行うために用います。上記のプログラムでは、青色で塗りつぶすように設定しています。そして、Canvas に用意されている円を描画するメソッド drawCircle() を用いて、円を描画します。
「drawCricle()」メソッドの書式は次のようになっています。描画設定には、Paint クラスのインスタンスを指定します。
drawCricle(中心点X座標,中心点Y座標,半径の幅,描画設定)
円を描画する他に、どんな描画ができるのかは、Android の API マニュアルに詳しく記述されています。
これを見ると、線を描画する drawLine() 、任意のパスを描画する drawPath() 、矩形を描画する drawRect()、角丸の矩形を描画する drawRoundRect()、テキストを描画する drawText() と、さまざまなものが用意されていることが分かります。
円を移動させてみる
次に、定期的に円を動かしてみます。以下は、ランダムに円を動かすプログラムです。500msecに一回再描画するタイミングで、ランダムな位置に円を描画しています。
上で作った TestCircle.java の内容を以下のように書き換えて実行してみてください。
// file:TestCircle.java
package com.example.android.circle;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.os.Bundle;
import android.view.View;
/** メインクラス */
public class TestCircle extends Activity {
/** 画面描画用 View */
MyCircleView view;
/** Timer 処理用のハンドラ */
android.os.Handler handler = new android.os.Handler();
/** Activityが生成された時に呼ばれる */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// View の設定
view = new MyCircleView(getApplication());
setContentView(view);
// Timer の設定をする
Timer timer = new Timer(false);
timer.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
view.invalidate();
}
});
}
},0, 500);
}
}
/** View クラス */
class MyCircleView extends View {
// View の初期化
public MyCircleView(Context context) {
super(context);
setFocusable(true);
}
public int displayWidth;
public int displayHeight;
// 実際に描画を行うメソッド
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 背景色の設定
canvas.drawColor(Color.WHITE);
// 描画オブジェクトの生成
Paint paint = new Paint();
paint.setAntiAlias(true);
// 円を適当な位置に描画する
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
float cx = (float)Math.random() * displayWidth;
float cy = (float)Math.random() * displayHeight;
canvas.drawCircle(cx, cy, 30, paint);
}
/** 画面サイズが変更されたときに呼び出されるメソッド */
protected void onSizeChanged(int w, int h, int oldw, int oldh){
displayWidth = w;
displayHeight = h;
}
}
ここで、追加した部分は、Timer で定期的に再描画行うようにしたのと、ディスプレイのサイズを取得して描画するようにしています。ディスプレイのサイズを取得するには、View クラス(を継承して作ったクラス)で、onSizeChanged() メソッドを作ることで、取得できます。
そして、定期的に再描画を行うために、Timer クラスを利用しています。この中で、invalidate() メソッドを呼び出すことで、再描画を促しています。(直接、onDraw() メソッドを呼ぶべきではありません。)
そして、Timer を使った場合、イベントは別スレッドで実行されますので、定期的なタイマーを処理する中で、GUI を操作する invalidate() メソッドを呼ぶことはできません。
view.invalidate(); // タイマーの中では直接呼べない
そこで、android.os.Handler を利用して、post() メソッドを利用して GUI を更新するようにします。Timer でスレッドを分けてしまうと、ちょっと処理が複雑になってしまいますが、仕方ありません。
....
android.os.Handler handler = new android.os.Handler();
public void onCreate(Bundle savedInstanceState) {
....
Timer timer = new Timer(false);
timer.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
view.invalidate();
}
});
}
},0, 500);
....
まとめ
以上、今回は、円を描画し、それを定期的に動かすというところまで処理を作ってみました。次回は、実際に遊べる簡単なゲームを作って遊んでみようと思います。お楽しみに。
TrackBack URL :










[…] wrote “invalidate()” . But it did not work. I looked in the web and find the solution. (reference page) The timer uses the thread, so it can not call “invalidate()” function directly. To do […]
Posted by A moving car : Simple Animation : Android Programming | Have a Cup of Coffee? | 2011年03月03日 22:03