課題 (09:キャンバス)

作業について

今回の課題は以下のパッケージに作成してください。

パッケージの名前
j1.lesson09

作成するクラスの名前は問題ごとに指示があります。下記を参照してください

課題の提出方法については下記を参照してください。

また、別のコンピューター上に移動する際には、下記を参考にプログラムを持ち帰ってください。

新しい内容

今回、キャンバスに関する新しい内容はありません。

問題

作成するクラスの名前
PaintS2

利用者がキャンバス上に絵を描けるプログラムを作成してください。

図: お絵描きプログラム

それぞれの操作は、まずボタンを押してから行います。今回は次のようにボタンを4つ使います。

ボタンのラベル 概要
キャンバス上を2点クリックして、2点間の線分を描画する
(Canvas.drawLine)
文字列 キャンバス上を1点クリックしたのちに入力ダイアログに文字列を入力すると、
クリックした点を左下に入力された文字列を描画する
(Canvas.drawString)
楕円 キャンバス上を2点クリックして、それぞれの点を左上と右下に持つ長方形に内接するような楕円を描画する
(Canvas.drawOval)
終了 「終了」とメッセージダイアログに表示し、以後の操作を受け付けなくする。

たとえば線を引く場合には「線」というボタンを押してから、キャンバス上の2点をクリックするとその2点を結ぶ線が引かれます。一つの操作が終わると、またボタンを押して次の操作を行います。これを繰り返して絵を描いていくようなプログラムです。

a. ボタンの作成

まずは次のようなボタンをキャンバス上に描画してください。

図: ボタンの作成

そして、それぞれのボタンが押されたら、下記の表にある押されたボタンの機能説明をメッセージダイアログ上に表示するようにしてください。

ボタンのラベル 機能説明
2点をクリックして線を描きます
文字列 1点をクリックして文章を書きます
楕円 2点をクリックして楕円を描きます
終了 プログラムを終了します

どれかボタンを押してメッセージを表示した後は、さらに次のボタンを押せるようにしてください。

また、ボタンでない個所がクリックされた場合には「ボタンをクリックしてください」と表示してまた次のボタンを押せるようにしてください。

ただし、「終了」ボタンが押された場合にはメッセージダイアログに機能説明を表示したあと、そこで繰り返しを終了させて、その後はボタンを押せないようにしてください。

なお、以後の課題ではそれぞれのボタンの機能を作成して行くことになります。ここでは、ボタンに対応するメソッドをそれぞれ宣言して、対話ループ(whileによる繰り返し)から起動するようなプログラムを作成してください。

void drawLine() {
    JOptionPane.showMessageDialog(null, "2点をクリックして線を描きます");
}

void drawString() {
    JOptionPane.showMessageDialog(null, "1点をクリックして文章を書きます");
}

void drawOval() {
    JOptionPane.showMessageDialog(null, "2点をクリックして楕円を描きます");
}

なお、「終了」ボタンに対応するメソッドは特に必要ありません。

ヒント

「ボタン」を表すクラスを作成して4つのボタンに対応する4つのインスタンスを作成するとプログラムが読みやすくなります (クラスに慣れていないとちょっと難しいので、復習してみてください)。

性質 概要
label ボタンの中に表示する文字列。ボタンを描画する際に使う。
x ボタンを描画するX座標。ボタンがクリックされた際の判定にも使える。
y ボタンを描画するY座標。ボタンがクリックされた際の判定にも使える。
id ボタンの番号。「どのボタンが押されたか?」ということを判定する際に使う。

これを配列にしておくとさらに便利で、次のようにfor文を使ってボタンの描画やクリックの判定などが書けます。

for (int i = 0; i < array.length; i++) {
    Button button = array[i];
    int x = button.x;
    int y = button.y;
    String label = button.label;
    <ボタンを描画する処理>
}
for (int i = 0; i < array.length; i++) {
    Button button = array[i];
    int x = button.x;
    int y = button.y;
    int id = button.id;
    if (<領域を判定する処理>) {
        return id;
    }
}
<ボタン以外の領域がクリックされた場合の処理>

b. 線の描画

ボタン「線」がクリックされたら、そのあとにキャンバス上の2点をクリックして、2点間の線を描画するようにしてください。先ほどまで「線」をクリックした際に表示していたメッセージダイアログは表示しないようにしてください。

図: 線の描画

線を引き終わったら、さらにボタン「線」をクリックして、次の線が引けることも確認してください。

図: 次の線の描画

ヒント

作成した機能の動きを確認する際には、次のようにstartメソッドの先頭(Canvas.show()の直後)で、「線」ボタンに対応するメソッドを起動してやると楽かもしれません。

void start() {
    Canvas.show();
    drawLine();
    
    ... (元のプログラム)
}

上記の例では、プログラムを実行した際にまずdrawLineメソッドを起動し、そのあとに実際のプログラムが実行されるようになります。

確認を終了したら、startメソッドに挿入した部分を元に戻しておきましょう。

c. 文字列の描画

ボタン「文字列」がクリックされたら、そのあとにキャンバス上の1点をクリックして、さらに入力ダイアログを表示してください。入力ダイアログに文字列が入力されたら、それをクリックされた点を左下として描画してください。

図: 文字列の描画

文字列を描画したら、さらにボタン「線」や「文字列」をクリックして、次の描画が行えることも確認してください。

図: 文字列や線の描画

d. 楕円の描画

ボタン「楕円」がクリックされたら、そのあとにキャンバス上の2点をクリックして、それぞれの点を左上と右下(または左下と右上)に持つ長方形に内接するような楕円を描画するようにしてください。

図: 楕円の描画

文字列を描画したら、さらにボタン「線」や「文字列」をクリックして、次の描画が行えることも確認してください。

図: お絵描きプログラム

ヒント

楕円を描画する「Canvas.drawOval」の3つ目と4つ目の引数は幅と高さを指定します。そのため、2点をクリックした際の座標から、これらの値を計算する必要があります。また、幅と高さは正の値でなければなりませんので、少しだけ計算が必要になります。

ヒント

この座標系での「左上の点」とは「長方形の頂点のうち、原点(0, 0)に最も近い点」のことです。つまり、2点のX座標のうち小さいもの、2点のY座標のうち小さいもの、をそれぞれ計算することになります。また、幅や高さは2点のX座標の差の絶対値、Y座標の差の絶対値、でそれぞれ計算できます。

画像の保存 (おまけ)

以上でお絵描きプログラムの作成は終わりです。キャンバスのメニューバーから「ファイル」「保存」の順に選択すると、描画した画像を保存できますので、試してみてください。