プログラミング演習3

プログラミング演習3
第3回 ミニプロジェクト
ミニプロジェクトについて
• 1週目では丸や三角形などの形状を用いて
継承の復習、2週目ではボタンなどのレイア
ウトや図形の描画などGUIの復習をしました
• ミニプロジェクトでは、これら2つを組み合わ
せておえかきツールを作ってみましょう
完成図の例
図形選択パネル
メニュー
描画パネル
1) ボタンを選択
-> 選択された図形の描画準備
2) 描画パネルをクリック -> 選択された図形をクリックされた
座標に描画
ミニプロジェクトの流れ
•
•
•
•
基本図形クラスの設計
お絵かきツールの作成
複合図形クラスの設計
発展
基本図形クラスの設計
描画クラスの定義
• 基本的(primitive)な図形と複合的(compound)
な図形を分けて考える
複合的
基本的
• 描画に必要なメソッドを考え、インターフェー
スにまとめる
実現したいこと
(機能)
必要なこと
(メソッド)
基本的な図形クラスの設計
?
Interface Drawable
Shape
void draw(int x, int y, Graphics g)
void setColor(Color c)
Polygon
Rectangle
?
・
・
・
?
Circle
Square
?
? IsoscelesTriangle
?
SmallRectangle
BigRectangle
SmallSquare
BigSquare
SmallCircle
SmallIsoscelesTriangle
BigIsoscelesTriangle
BigCircle
 全ての基本図形がDrawable のメソッドを使える
描画に必要なメソッド
• 塗りつぶさずに描画 -> draw(int x, int y, Graphics g)
• 塗りつぶして描画 -> drawfill(int x, int y, Graphics g)
– 色の設定と取得 -> setColor(Color c), getColor()
– 塗りつぶすか選択 -> setFilled(Boolean b), getFilled()
・
・
・
drawable[2] = new BigCircle();
drawable[3] = new BigCircle();
drawable[3].setColor(Color.BLUE);
drawable[3].setFilled(true);
・
・
・
• ボタンに画像を貼る -> getImage() : draw(…), drawfill(…) を場合分け
• 画像サイズを決定する -> getWidth(), getHeight()
BigCircle クラスの実装例 (1/3)
(Shape クラス)
protected 修飾子はサブク
ラスのみがアクセス範囲
BigCircle クラスの実装例 (2/3)
(Circle クラス)
BigCircle クラスの実装例 (3/3)
お絵かきツールの作成
メニューの作り方
メニューを作るには
JMenuBar,Jmenu,JMenuItemを用いる
JMenuBar
L JMenu
L JMenuItem
の構造になっていて、JMenuItemをクリッ
クした時にイベントを発生させたい場合は
JButtonと同様にActionListenerに登録し、
actionPerformedメソッド内に処理を書く
表示する文字列やショート
カットキーの設定
終了を押した時の処理
描画パネルと図形選択パネルの配置
JPanelを継承したクラスを作り、実行クラス内で呼び出す
class MainFrame extends JFrame{
ChoosePanel cp;
DrawPanel dp;
class ChoosePanel extends JPanel{
}
class DrawPanel extends JPanel{
}
ボタンの作成
イベントを発生させたいコンポーネントに
リスナー(ボタンの場合はActionListener)を指定
イベントを発生した時に行う処理を書く
ボタンによって処理を変えたい場合は
getSourceやgetActionCommandで場合分け
ボタンに貼る画像の作り方
まず図形クラスで、図形の大きさに合った
BufferedImageを作成しdrawメソッドで描いた
ものをImageとして返す
ボタンに画像を貼る方法
getImageメソッドで生成した
画像は図形によって大きさが
異なるので、一定の大きさに
縮小してからボタンに貼り付
ける
パネルへの配置例
:
private Drawable[] drawable;
private Jlabel[] l;
縦2,横2で配置
private Jbutton[] b;
:
setLayout(new GridLayout(2, 2));
drawable[0] = new BigCircle();
drawable[1] = new SmallIsoscelesTriangle();
for(int i=0; i<drawable.length(); i++) {
l[i] = new JLabel(drawable[i].toString(), SwingConstants.CENTER);
add(l[i]);
img = drawable[i].getImage();
newimg = img.getScaledInstance(imagesize, imagesize,
java.awt.Image.SCALE_SMOOTH);
b[i] = new JButton(new ImageIcon(newimg));
b[i].addActionListener(this);
レイアウトマネージャーを無効にして絶対座標で指定す
add(b[i]);
る方法もあります
}
http://www.javadrive.jp/tutorial/nulllayout/index1.html
Graphicsクラスによる描画
描画はpaintComponentメソッド
で行う
描画には以下のようなメソッド
が用意されている
文字列の描画
線の描画
四角形の描画
丸の描画
多角形の描画
:drawstring(表示する文字列,x座標,y座標)
:drawLine(始点のx座標,y座標,終点のx座標,y座標)
:drawRect(x座標,y座標,横幅,高さ)
:drawOval(x座標,y座標,横幅,高さ)
:drawPolygon(x座標の配列,y座標の配列,頂点数)
塗りつぶす場合は
draw~をfill~に変える
継承を生かした描画
SmallCircleもBigCircleも大きさが異なるだけで描
画する方法は同じなのでCircleクラスに処理をま
とめることができる
Circleクラス
SmallCircleクラスと
BigCircleクラスにはdrawメ
ソッドが書かれていないの
で継承元のCircleクラスの
drawメソッドが呼ばれる
SmallCircleクラス
BigCircleクラス
クリックしたところに描画する
mouseClickメソッド内
でクリックした座標を
取得し、描画を行う
←2回めの課題の
解答例
図形とクリックした場所の保持
private ArrayList<ShapeObject> shapes=new ArrayList<ShapeObject>();
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < shapes.size(); i++)
shapes.get(i).pd.draw(shapes.get(i).p.x,shapes.get(i).p.y, g);
}
追加された形状を全て描画
@Override
public void mouseClicked(MouseEvent e) {
Point p = e.getPoint();
shapes.add(new ShapeObject(currentDrawable, p));
repaint();
}
クリックされたら形状と座標を追加
:
private class ShapeObject {
描画する形状と座標を保つクラス
Drawable d;
Point p;
public ShapeObject(Drawable d, Point p){
this.pd = pd;
this.p = p;
}
}
repaintメソッドで再描画す
ると、これまでに描画してい
たものは消えてしまうので、
LinkedHashMapやArrayList
を使ってこれまでに描画し
た図形と描画した座標を保
持する
←実装例
複合図形クラスの定義
基本図形クラスとの違い
複合的
基本的
Drawable
継承
CompoundDrawable
共通なメソッドと特有なメソッドを分け、それぞれのインター
フェースにまとめる
draw(int x, int y, Graphics g)
drawfill(int x, int y, Graphics g)
setColor(Color c)
getColor()
setFilled(Boolean b)
getFilled()
getImage()
getWidth()
getHeight()
getParts()
setDefaultColor()
CompoundDrawable
Treeクラスの指針
• 課題1で設計したTreeクラスに描画処理を実装する
• 基本図形と共通のメソッドはP. 9 - 11のBigCircleの実装例を
参考する
• 複合図形はパーツ毎に色が異なるため、drawメソッドでは
デフォルトカラーを指定するsetDefaultColorメソッドを呼ぶ
必要がある
drawメソッド
drawfillメソッド
drawメソッド
drawfillメソッド
発展
複合図形クラスをもっと簡潔に
複合的な図形でも共通の処理を抽象クラスにまとめると便利
継承
継承
他の複合的な形状のクラス
スライド7を参考にするとよい
スクロールバーをつける
表示するものが大きすぎてフレームやパネルに収まり切らない
場合はスクロールバーをつけると便利です
ALWAYSに指定したためフレームに収まっ
ていてもスクロールバーが出る
バーを出す条件
AS_NEEDEDと指定し、フレームに収ま
らなかったためスクロールバーが出た
ファイルの読込み
ファイルを読み込んでキャンバ
スに張り付けたり、作品を画像
ファイルとして保存する
ユーザに開くファイルを選んで貰う場
合はFileDialogを使う
ユーザがファイルを選択した場合、
ファイルまでのパスとファイル名を取
得できるが、画像として読み込むのか、
中のテキストを読み込むのかは自分
で実装する必要がある
その他
•
•
•
•
Ctrl+ZでUndo機能をつける
getPartsメソッドを活かした描画の実現
図形を拡大・縮小して描画
描画前にプレビュー
など
実装の過程
Step1
Step2
Step3
• Circleクラスを参考にして四角形や三角形などの基本図形クラスを作る
• お絵かきツールを作成し、メニューバー、描画パネルと図形選択パネルを配置する
• 図形選択パネルにStep1で作成した図形の画像を貼り付けたボタンを表示する
• 図形選択パネルのボタンを選んで、描画パネル上でクリックすると、クリックした場所に図形が描画さ
Step4 れる
Step5
目標
• 複合図形クラスに共通するメソッドをまとめたCompoundDrawableを定義し、Treeクラスを描画する
• TreeクラスのようなDrawableを実装するクラスをメンバーに持つ複合図形クラスを3個以上作る
• CompoundFigureクラスを定義し、複合図形クラスに共通する処理をまとめ、Step5で作ったクラスの
発展1 Superクラスとする
発展2
• おえかきツールにオリジナルの機能を追加する(Undoとかキャプチャとか)