プログラミング演習3 - 法政大学 情報科学部

プログラミング演習3
第3回 ミニプロジェクト
ミニプロジェクトについて
• 1週目では丸や三角形などの形状を用いて
継承の復習、2週目ではボタンなどのレイア
ウトや図形の描画などGUIの復習をしました
• ミニプロジェクトでは、これら2つを組み合わ
せておえかきツールを作ってみましょう
完成図の例
図形選択パネル
メニュー
描画パネル
1) ボタンを選択
-> 選択された図形の描画準備
2) 描画パネルをクリック -> 選択された図形をクリックされた
座標に描画
ミニプロジェクトの流れ
• Swingによる描画
– 描画パネルと図形選択パネルの設計
– ActionListenerの処理の記述
– Graphicsクラスによる描画
• 描画クラスの定義
– 図形クラスの設計
– 描画用インターフェースの設計
• 複合図形の描画
描画パネルと図形選択パネルの設計
JPanelを継承したクラスを作り、実行クラス内で呼び出す
class MainFrame extends JFrame{
ChoosePanel cp;
DrawPanel dp;
class ChoosePanel extends JPanel{
}
class DrawPanel extends JPanel{
}
ActionListenerの処理の記述
イベントを発生させたいコンポーネントに
リスナー(ボタンの場合はActionListener)を指定
イベントを発生した時に行う処理を書く
ボタンによって処理を変えたい場合は
getSourceやgetActionCommandで場合分け
ボタンに貼る画像の作り方
まず図形クラスで、図形の大きさに合った
BufferedImageを作成しdrawメソッドで描いた
ものをImageとして返す
サイズが(70,70)の空のイメージを作成
し、そこにTreeを構成する要素を描く
作成する画像の横幅を返すメソッド
作成する画像の高さを返すメソッド
※Treeクラスについてはスライド23,24を参考にすること
ボタンに画像を貼る方法
getImageメソッドで生成した
画像は図形によって大きさが
異なるので、一定の大きさに
縮小してからボタンに貼り付
ける
パネルへの配置例
private Drawable drawable;
private JLabel l;
private JButton b;
縦1,横2で配置
:
setLayout(new GridLayout(1, 2));
drawable = new Tree();
l = new JLabel(drawable.toString(), SwingConstants.CENTER);
add(l);
img = drawable.getImage();
newimg = img.getScaledInstance(imagesize, imagesize,
java.awt.Image.SCALE_SMOOTH);
b = new JButton(new ImageIcon(newimg));
b.addActionListener(this);
レイアウトマネージャーを無効にして絶対座標で指定す
add(b);
る方法もあります
http://www.javadrive.jp/tutorial/nulllayout/index1.html
描画に必要なメソッド
• 塗りつぶさずに描画 -> draw(int x, int y, Graphics g)
• 塗りつぶして描画 -> drawfill(int x, int y, Graphics g)
– 色の設定と取得 -> setColor(Color c), getColor()
– 塗りつぶすか選択 -> setFilled(Boolean b), getFilled()
ChoosePanel( ) {
・
・
・
drawable[0] = new Tree();
drawable[1] = new Tree();
drawable[2] = new BigCircle();
drawable[3] = new BigCircle();
drawable[1].setColor(Color.PINK);
drawable[1].setFilled(true);
drawable[3].setColor(Color.BLUE);
drawable[3].setFilled(true);
・
・
・
• ボタンに画像を貼る -> getImage() : draw(…), drawfill(…) を場合分け
• 画像サイズを決定する -> getWidth(), getHeight()
Graphicsクラスによる描画
描画はpaintComponentメソッド
で行う
描画には以下のようなメソッド
が用意されている
文字列の描画
線の描画
四角形の描画
丸の描画
多角形の描画
:drawstring(表示する文字列,x座標,y座標)
:drawLine(始点のx座標,y座標,終点のx座標,y座標)
:drawRect(x座標,y座標,横幅,高さ)
:drawOval(x座標,y座標,横幅,高さ)
:drawPolygon(x座標の配列,y座標の配列,頂点数)
塗りつぶす場合は
draw~をfill~に変える
クリックしたところに描画する
mouseClickメソッド内
でクリックした座標を
取得し、描画を行う
←2回めの
Homeworkの解答例
図形とクリックした場所の保持
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やAllayList
を使ってこれまでに描画し
た図形と描画した座標を保
持する
←実装例
継承を生かした描画
SmallCircleもBigCircleも大きさが異なるだけで描
画する方法は同じなのでCircleクラスに処理をま
とめることができる
Circleクラス
SmallCircleクラスとBigCircleクラスには
drawメソッドが書かれていないので継
承元のCircleクラスのdrawメソッドが
呼ばれる
SmallCircleクラス
BigCircleクラス
メニューの作り方
メニューを作るには
JMenuBar,Jmenu,JMenuItemを用いる
JMenuBar
L JMenu
L JMenuItem
の構造になっていて、JMenuItemをクリッ
クした時にイベントを発生させたい場合は
JButtonと同様にActionListenerに登録し、
actionPerformedメソッド内に処理を書く
表示する文字列やショート
カットキーの設定
終了を押した時の処理
描画クラスの定義
• 基本的(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) の宣言はどこ?
 Tree の中で宣言?
Interface Drawable
draw(int x, int y, Graphics g)?
・
・
・
 CompoundDrawable の中で宣言?
 Drawable から継承?
Interface CompoundDrawable
getParts()の返り値は何?
 あらゆる図形を複数入れれる箱は..?
Tree
getParts()
draw( int x, int y, Graphics g)?
draw( int x, int y, Graphics g)?
BigIsoscelesTriangle
SmallSquare
SmallIsoscelesTriangle
BigIsoscelesTriangle
描画に必要なメソッド
• 塗りつぶさずに描画 -> draw(int x, int y, Graphics g)
• 塗りつぶして描画 -> drawfill(int x, int y, Graphics g)
– 色の設定と取得 -> setColor(Color c), getColor()
– 塗りつぶすか選択 -> setFilled(Boolean b), getFilled()
ChoosePanel( ) {
・
・
・
drawable[0] = new Tree();
drawable[1] = new Tree();
drawable[2] = new BigCircle();
drawable[3] = new BigCircle();
drawable[1].setColor(Color.PINK);
drawable[1].setFilled(true);
drawable[3].setColor(Color.BLUE);
drawable[3].setFilled(true);
・
・
・
• ボタンに画像を貼る -> getImage() : draw(…), drawfill(…) を場合分け
• 画像サイズを決定する -> getWidth(), getHeight()
BigCircle クラスの実装例
(Shape クラス)
protected 修飾子はサブク
ラスのみがアクセス範囲
BigCircle クラスの実装例
(Circle クラス)
BigCircle クラスの実装例 (/3)
Tree クラスの実装例 (1/2)
Tree クラスの実装例 (2/2)
Treeクラスをもっと簡潔に
複合的な図形では、使用するパーツの定義と描画する座標の設定以
外の処理はほとんど共通の処理を抽象クラスにまとめて書くと便利
継承
継承
他の複合的な形状のクラス
実装の過程
Step1
Step2
• Circleクラスを参考にして四角形や三角形などの基本図形を作る
• 図形選択パネルにStep1で作成した図形の画像を貼り付けたボタンを表示する
• 図形選択パネルのボタンを選んで、描画パネル上でクリックすると、クリックした場所に図形が描画さ
Step3 れる
• 複合的な図形を実装する上で共通のメソッドをまとめたCompoundFigureクラスを定義し、Treeクラス
Step4 などの複合的な図形を表すクラスに継承させる
Step5
• おえかきツールでStep4で作成した図形を描画できるようにする
• TreeクラスのようなCompoundDrawbleを継承するクラスをメンバーに持つCompoundDrawbleを継承
Step6 したクラスを5個以上作る
Step7
Step8
• メニューにヘルプの項目を作り、クリックすると作成者の名前が書かれたダイアログを表示させる
• おえかきツールにオリジナルの機能を追加する(Undoとかキャプチャとか)