マウスのイベントを受け取って処理するプログラムを作成する。 ユーザからの入力に反応するプログラムを作成できる。
描画するウィンドウに対するマウス操作のイベントを受け取るクラスは、 ToyGraphics の(正確にはその祖先の java.awt.Component の) subclassである必要があります。
生成したウィンドウへのマウス操作のイベントを受け取るためには、 MouseLisenter インターフェイスを implements して addListener(MouseListener) を呼び出す必要があります。
Sample08.java |
import java.awt.*; import java.awt.geom.*; import java.awt.event.*; public class Sample4 extends ToyGraphics implements MouseListener { public Sample4() { super(640,480); } public void run() { addMouseListener(this); // ウィンドウに対するMouseイベントを自分で受け取る g2d.setPaint(Color.white); g2d.fill(new Rectangle2D.Double(0, 0, width, height)); // ウィンドウ全体を黒で塗りつぶす repaint(0,0,width,height); // 範囲を指定して再描画する (これが無いと変更が反映されない) } public void mouseClicked(MouseEvent e) { System.err.println("mouseClicked"); } public void mousePressed(MouseEvent e) { int mx = e.getX(), my = e.getY(); System.err.println("mousePressed " + mx + " " + my); int w=10, h=10, x=mx-w/2, y=my-h/2; g2d.setPaint(Color.blue); g2d.fill(new Rectangle2D.Double(x,y,w,h)); // (x,y)の回りを10x10の青色の四角で塗りつぶす repaint(x,y,w,h); } public void mouseReleased(MouseEvent e) { int mx = e.getX(), my = e.getY(); System.err.println("mouseReleased " + mx + " " + my); int w=10, h=10, x=mx-w/2, y=my-h/2; g2d.setPaint(Color.red); g2d.fill(new Rectangle2D.Double(x,y,w,h)); // (x,y)の回りを10x10の赤色の四角で塗りつぶす repaint(x,y,w,h); } public void mouseEntered(MouseEvent e) { System.err.println("mouseEntered"); } public void mouseExited(MouseEvent e) { System.err.println("mouseExited"); } public static void main(String[] args) { Sample4 app = new Sample4(); app.run(); } } |
Sample08.java の実行例 |
% java Sample3 mouseEntered mousePressed 104 83 mouseReleased 192 170 mousePressed 276 201 mouseReleased 236 295 mousePressed 394 395 mouseReleased 397 227 |
WinDraw.java |
import java.util.*; import java.awt.*; import java.awt.geom.*; import java.awt.event.*; public class WinDraw extends ToyGraphics implements MouseListener { static final int RECTANGLE = 1; static final int CIRCLE = 2; boolean isDragging = false; int sx, sy, ex, ey; // Mouse pressed (sx,sy), released (ex,ey) Color strokeColor = Color.red; int shapeType = RECTANGLE; int[][] menuArea = { {0,0,100,30}, {0,30,100,30}, {0,60,100,30}, {0,90,100,30}, {0,120,100,30}, }; String[] menuString = { "Redraw", "Red", "Blue", "Rectangle", "Circle" }; ArrayList<Shape> shapes; public WinDraw() { this(1280,720); } public WinDraw(int w,int h) { shapes = new ArrayList<Shape>(); addMouseListener(this); } public void run() { redraw(); } boolean inArea(int mx,int my,int x,int y,int w,int h) { return (mx >= x && mx < x+w && my >= y && my < y+h); } boolean inArea(int mx,int my,int[] r) { int x=r[0], y=r[1], w=r[2], h=r[3]; return (mx >= x && mx < x+w && my >= y && my < y+h); } boolean checkMenu(int sx,int sy) { for (int i = 0; i<menuArea.length; i++) { int[] r= menuArea[i]; if (inArea(sx,sy,r)) { System.err.println("menu "+i); switch (i) { case 0: redraw(); break; case 1: strokeColor = Color.red; break; case 2: strokeColor = Color.blue; break; case 3: shapeType = RECTANGLE; break; case 4: shapeType = CIRCLE; break; default: System.err.println("no menu"); System.exit(-1);break; } return true; } } return false; } void redraw() { g2d.setPaint(Color.black); g2d.fill(new Rectangle2D.Double(0,0,width,height)); drawMenu(); for (Shape shape: shapes) { shape.draw(g2d); } repaint(0,0,width,height); } void drawMenu() { for (int i=0; i<menuArea.length; i++) { int[] r = menuArea[i]; Rectangle2D shape = new Rectangle2D.Double(r[0],r[1],r[2],r[3]); g2d.setPaint(Color.white); g2d.fill(shape); g2d.setPaint(Color.black); g2d.draw(shape); g2d.drawString(menuString[i], r[0]+5, r[1]+20); repaint(r[0],r[1],r[2],r[3]); } } public void mouseClicked(MouseEvent e) {} public void mousePressed(MouseEvent e) { sx = e.getX(); sy = e.getY(); System.err.println("Pressed " + sx + " " + sy); isDragging = !checkMenu(sx,sy); } public void mouseReleased(MouseEvent e) { ex = e.getX(); ey = e.getY(); System.err.println("Released " + ex + " " + ey); if (! isDragging) return; // select menu int x = Math.min(sx,ex), y = Math.min(sy,ey), w = Math.abs(ex-sx), h = Math.abs(ey-sy); Shape shape; if (shapeType == RECTANGLE) { shape = new Rect(x,y,w,h,3,strokeColor,null); } else { // (shapeType == CIRCLE) shape = new Circle(x,y,w,h,3,strokeColor,null); } shape.draw(g2d); repaint(x,y,w,h); shapes.add(shape); } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public static void main(String[] args) { WinDraw wd = new WinDraw(); wd.run(); } } |
Shape.java |
import java.awt.*; public abstract class Shape { int x, y; Color strokeColor, fillColor; abstract void draw(Graphics2D g2d); } |
Rect.java |
import java.awt.*; import java.awt.geom.*; public class Rect extends Shape { int w, h, lineWidth; public Rect(int x,int y,int w,int h,int lineWidth,Color strokeColor,Color fillColor) { this.x = x; this.y = y; this.w = w; this.h = h; this.lineWidth = lineWidth; this.strokeColor = strokeColor; this.fillColor = fillColor; } void draw(Graphics2D g2d) { Rectangle2D shape = new Rectangle2D.Double(x,y,w,h); if (fillColor != null) { g2d.setPaint(fillColor); g2d.fill(shape); } if (strokeColor != null) { g2d.setStroke(new BasicStroke((float) lineWidth)); g2d.setPaint(strokeColor); g2d.draw(shape); } } } |
Circle.java |
import java.awt.*; import java.awt.geom.*; public class Circle extends Shape { int w, h, lineWidth; public Circle(int x,int y,int w,int h,int lineWidth,Color strokeColor,Color fillColor) { this.x = x; this.y = y; this.w = w; this.h = h; this.lineWidth = lineWidth; this.strokeColor = strokeColor; this.fillColor = fillColor; } void draw(Graphics2D g2d) { Arc2D shape = new Arc2D.Double(x,y,w,h,0,360,Arc2D.OPEN); if (fillColor != null) { g2d.setPaint(fillColor); g2d.fill(shape); } if (strokeColor != null) { g2d.setStroke(new BasicStroke((float) lineWidth)); g2d.setPaint(strokeColor); g2d.draw(shape); } } } |
WinDraw.java の実行例 |
% javac WinDraw.java % java WinDraw Pressed 11 46 menu 1 Released 11 46 Pressed 65 103 menu 3 Released 65 103 Pressed 251 163 Released 430 315 Pressed 54 131 menu 4 Released 56 132 Pressed 683 272 Released 967 479 Pressed 30 74 menu 2 Released 31 74 Pressed 372 120 Released 683 382 Pressed 73 109 menu 3 Released 73 109 Pressed 135 273 Released 609 582 |
敢えて、ToyGraphicsの生成する1つのウィンドウだけで作ってみた「お絵描きツール」です。 ウィンドウの中に領域を定義してメニューとして何か表示して、それをクリックすることで状態を変化させます。 メニュー以外のウィンド領域はマウスボタンの「押す」「放す」イベントにより図形を配置します。
もっとオブジェクト指向らしいプログラムの書き方はありえますが、 ここでは「敢えて」目先の単純さを優先したプログラム例を示していると理解して下さい。 改善策はいろいろあります。特に「メニュー」回りの扱いは大いに改善の余地があることでしょう。
ウス入力を扱うJavaのプログラムを作成して下さい。 ファイル名は GReport04.java としましょう。
正しく動作するプログラムのみを提出すること。
作成したプログラムが正しく動作することを確認したら、 「宿題提出Web:1年ゼミ:課題4」 http://nw.tsuda.ac.jp/class/1semi/local/handin/up.php?id=kadai4 から提出して下さい。 提出ページの 「提出ファイル」に自分が作成した GReport04.java を指定し、 「コメント欄」には何の絵であるかの説明を記入して下さい。
提出した後は、正しく提出されていることを http://nw.tsuda.ac.jp/class/1semi/local/handin/list.php?id=kadai4 で必ず確認しておいて下さい。
〆切は1週間後の10:30です。