260 likes | 425 Views
プログラミング演習3. 第3回 ミニプロジェクト. ミニプロジェクトについて. 1週目では丸や三角形などの形状を用いて継承の復習、2週目ではボタンなどのレイアウトや図形の描画など GUI の復習をしました ミニプロジェクトでは、これら2つを組み合わせておえかきツールを作ってみましょう. 完成図の例. 図形選択パネル. 描画パネル. メニュー. ボタンを選択 -> 選択された図形の描画準備 描画パネルをクリック -> 選択された図形をクリックされた 座標に描画. ミニプロジェクトの流れ. Swing による描画
E N D
プログラミング演習3 第3回 ミニプロジェクト
ミニプロジェクトについて • 1週目では丸や三角形などの形状を用いて継承の復習、2週目ではボタンなどのレイアウトや図形の描画などGUIの復習をしました • ミニプロジェクトでは、これら2つを組み合わせておえかきツールを作ってみましょう
完成図の例 図形選択パネル 描画パネル メニュー • ボタンを選択 -> 選択された図形の描画準備 • 描画パネルをクリック -> 選択された図形をクリックされた • 座標に描画
ミニプロジェクトの流れ • Swingによる描画 • 描画パネルと図形選択パネルの設計 • ActionListenerの処理の記述 • Graphicsクラスによる描画 • 描画クラスの定義 • 図形クラスの設計 • 描画用インターフェースの設計 • 複合図形の描画
描画パネルと図形選択パネルの設計 JPanelを継承したクラスを作り、実行クラス内で呼び出す class MainFrame extends JFrame{ ChoosePanelcp; DrawPaneldp; class ChoosePanel extends JPanel{ } class DrawPanelextends JPanel{ }
ActionListenerの処理の記述 イベントを発生させたいコンポーネントに リスナー(ボタンの場合はActionListener)を指定 イベントを発生した時に行う処理を書く ボタンによって処理を変えたい場合はgetSourceやgetActionCommandで場合分け
ボタンに貼る画像の作り方 まず図形クラスで、図形の大きさに合ったBufferedImageを作成しdrawメソッドで描いたものをImageとして返す サイズが(70,70)の空のイメージを作成し、そこにTreeを構成する要素を描く 作成する画像の横幅を返すメソッド 作成する画像の高さを返すメソッド ※Treeクラスについてはスライド23,24を参考にすること
ボタンに画像を貼る方法 getImageメソッドで生成した画像は図形によって大きさが異なるので、一定の大きさに縮小してからボタンに貼り付ける
パネルへの配置例 private Drawabledrawable; private JLabell; private JButtonb; : 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); 縦1,横2で配置 レイアウトマネージャーを無効にして絶対座標で指定する方法もあります 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() • ボタンに画像を貼る -> getImage() : draw(…), drawfill(…) を場合分け • 画像サイズを決定する -> getWidth(), getHeight() 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); ・・・ ・・・
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)な図形を分けて考える • 描画に必要なメソッドを考え、インターフェースにまとめる 複合的 基本的 実現したいこと (機能) 必要なこと (メソッド)
基本的な図形クラスの設計 ? Shape InterfaceDrawable void draw(int x, int y, Graphics g) void setColor(Color c) ? Polygon ? Rectangle ・・・ Circle Square ? ? ? IsoscelesTriangle SmallRectangle BigRectangle SmallCircle SmallSquare SmallIsoscelesTriangle BigIsoscelesTriangle BigSquare BigCircle • 全ての基本図形がDrawableのメソッドを使える
複合的な図形クラスの設計 • draw( int x, inty, Graphics g) の宣言はどこ? • Tree の中で宣言? • CompoundDrawableの中で宣言? • Drawableから継承? • getParts()の返り値は何? • あらゆる図形を複数入れれる箱は..? InterfaceDrawable draw(int x, inty, Graphics g)? ・・・ InterfaceCompoundDrawable getParts() draw( int x, int y, Graphics g)? Tree draw( int x, inty, Graphics g)? BigIsoscelesTriangle SmallIsoscelesTriangle BigIsoscelesTriangle SmallSquare
描画に必要なメソッド • 塗りつぶさずに描画 -> draw(int x, int y, Graphics g) • 塗りつぶして描画 -> drawfill(int x, int y, Graphics g) • 色の設定と取得 -> setColor(Color c), getColor() • 塗りつぶすか選択 -> setFilled(Boolean b), getFilled() • ボタンに画像を貼る -> getImage() : draw(…), drawfill(…) を場合分け • 画像サイズを決定する -> getWidth(), getHeight() 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); ・・・ ・・・
BigCircleクラスの実装例(Shape クラス) protected 修飾子はサブクラスのみがアクセス範囲
Treeクラスをもっと簡潔に 複合的な図形では、使用するパーツの定義と描画する座標の設定以外の処理はほとんど共通の処理を抽象クラスにまとめて書くと便利 継承 継承 他の複合的な形状のクラス