未経験からプログラマーを目指すならGEEK JOB 無料体験に参加してみませんか?
GEEK JOB編集部
前章までで、GUIを作ってプログラム側で図形を描くことはできました。
しかし、これだけではお絵かきソフトとは言えません。
絵を描くためには、マウスの座標を取得する必要があります。
Javaでは、マウスやキーボードの情報を取得するために、イベントリスナーというものを使います。
本章では、マウスの情報を取得するために、以下の2つのリスナーを扱います。
リスナー
監視するイベント
まずはMouseListenerを使って、クリックした場所に円を描くプログラムを書いてみます。
こちらが完成イメージです。
MouseListenerには5つのメソッドがあります。
以下にそれぞれのメソッドについて簡単にまとめました。
MouseListenerの各機能
イベント | 呼ばれるタイミング |
mouseClicked | コンポーネント上でマウスがクリックされた(押して離された)とき |
mousePressed | コンポーネント上でマウスボタンが押されたとき |
mouseReleased | コンポーネント上でマウスボタンが離されたとき |
mouseEntered | マウスがコンポーネント上に入ったとき |
mouseExited | マウスがコンポーネント上から出たとき |
MouseListenerを使うには、importに以下の文を追加する必要があります。
1 |
import java.awt.event.*; |
次にCanvasの宣言を、以下のように書き換えます。
1 |
class Canvas extends JPanel implements MouseListener |
extendsとよく似ていますね。
このように、MouseListenerをimplementsすれば、クラスをextendsしたときと同様、元になったクラス(この場合インターフェースと呼ばれるのですが)の機能を使うことができるようになります。
ただし、MouseListenerをimplementsした場合、MouseListenerに含まれていたすべてのメソッドを実装しなければいけません。
これを避けるテクニックもありますが(「MouseAdapter」で検索してみてください)、今回はすべて書いていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
class Canvas extends JPanel implements MouseListener { public Canvas() { setSize(600, 400); } @Override public void paintComponent(Graphics g) { g.setColor(Color.RED); g.drawOval(100, 100, 50, 50); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } } |
5つのメソッドが追加されています。
最後に、コンストラクタに以下の一文を書き加えます。
1 2 3 4 |
public Canvas() { addMouseListener(this); setSize(600, 400); } |
以上で、マウスの情報を取得する準備は整いました。
これから実際に、マウスでクリックした場所に、円を描画する処理を書いていきます。
まずは、クラスの頭に以下の2文を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
class Canvas extends JPanel implements MouseListener { private int x = -100; private int y = -100; public Canvas() { addMouseListener(this); setSize(600, 400); } @Override public void paintComponent(Graphics g) { g.setColor(Color.RED); g.drawOval(100, 100, 50, 50); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } } |
マウスの座標を格納する変数を宣言し、初期化しています。
今回は、paintComponent()とmousePressed()という2つのメソッド間で、マウスの座標をやり取りするので、共通して使用できる変数を用意する必要があります。
初期値を設定しないと、Javaではx,yに自動的に0が入りますが、こうすると起動時にpaintComponent()が呼ばれて、上記のように(0,0)の点(左上)に円が描画されてしまいます。
それを防ぐために、今回は(-100,-100)というウィンドウ外の値を指定しています。
次に、マウスのボタンが押されたときの処理を追加します。
1 2 3 4 5 |
public void mousePressed(MouseEvent e) { x = e.getX(); y = e.getY(); repaint(); } |
eは、マウスの座標や押されたボタンなどの情報を格納する変数で、マウスが押されたときに、自動的に情報が入っています。
今回は、e.getX()とe.getY()で、マウスの座標を取得しています。
最後に、x,yにマウス座標が入った状態で、repaint()メソッドでCanvasを再描画します。
repaint()を呼ぶことで、以下のpaintComponent()が呼ばれます。
1 2 3 4 5 |
public void paintComponent(Graphics g) { g.setColor(Color.RED); g.drawOval(100, 100, 50, 50); g.fillOval(x-5, y-5, 10, 10); } |
fillOval()は内部が塗りつぶされた楕円を描画するメソッドで、最初の2つの引数が座標、次の2つが円のサイズを表しています。
今回はmousePressed()で取得したマウスの位置に、直径10pxの円を描いています(ただしfillOval()で指定するのは円の左上の座標なので、円の中心とマウスの先端を合わせるために、半径5pxの値を差し引いています)。
以上の内容をすべて書き加えると、コード全体は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package simplepainter; import java.awt.Color; import java.awt.Graphics; import java.awt.event.*; import javax.swing.*; public class SimplePainter { public static void main(String[] args) { JFrame frame = new JFrame("SimplePainter"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600, 400); frame.setLocationRelativeTo(null); Canvas canvas = new Canvas(); frame.add(canvas); frame.setVisible(true); } } class Canvas extends JPanel implements MouseListener { private int x = -100; private int y = -100; public Canvas() { addMouseListener(this); setSize(600, 400); } @Override public void paintComponent(Graphics g) { g.setColor(Color.RED); g.drawOval(100, 100, 50, 50); g.fillOval(x-5, y-5, 10, 10); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { x = e.getX(); y = e.getY(); repaint(); } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } } |
以上のコードを追加したら、実行してみましょう。
ウィンドウ上でマウスをクリックしてみて、赤い点が描画されたら成功です。
今度は、マウスをドラッグすることで線を引けるようにしていきます。
こちらがが完成イメージです。
ドラッグ時のマウスの状態を取得するには、MouseListenerとは別に、MouseMotionListenerというリスナーが必要になります。
MouseMotionListenerには、以下の2つのメソッドがあります。
MouseMotionListenerの各機能
イベント | 呼ばれるタイミング |
mouseDragged | コンポーネント上でマウスがドラッグされているときに定期的に呼ばれる |
mouseMoved | コンポーネント上でマウスが動いているときに定期的に呼ばれる |
MouseListenerのときと同様、CanvasのimplementsにMouseMotionListenerを追加し、メソッドを追加していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
class Canvas extends JPanel implements MouseListener, MouseMotionListener { private int x = -100; private int y = -100; public Canvas() { addMouseListener(this); setSize(600, 400); } @Override public void paintComponent(Graphics g) { g.setColor(Color.RED); g.drawOval(100, 100, 50, 50); g.fillOval(x-5, y-5, 10, 10); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { x = e.getX(); y = e.getY(); repaint(); } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mouseDragged(MouseEvent e) { x = e.getX(); y = e.getY(); repaint(); } @Override public void mouseMoved(MouseEvent e) { } } |
MousePressed()と同様に、MouseDragged()内でマウスの座標をx,yに代入しておきました。
最後にコンストラクタ内にaddMouseMotionListener(this)を追加すれば、ドラッグ時の処理の追加は完了です。
1 2 3 4 5 |
public Canvas() { addMouseListener(this); addMouseMotionListener(this); setSize(600, 400); } |
すると、コード全体は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package simplepainter; import java.awt.Color; import java.awt.Graphics; import java.awt.event.*; import javax.swing.*; public class SimplePainter { public static void main(String[] args) { JFrame frame = new JFrame("SimplePainter"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600, 400); frame.setLocationRelativeTo(null); Canvas canvas = new Canvas(); frame.add(canvas); frame.setVisible(true); } } class Canvas extends JPanel implements MouseListener, MouseMotionListener { private int x = -100; private int y = -100; public Canvas() { addMouseListener(this); addMouseMotionListener(this); setSize(600, 400); } @Override public void paintComponent(Graphics g) { g.setColor(Color.RED); g.fillOval(x-5, y-5, 10, 10); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { x = e.getX(); y = e.getY(); repaint(); } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mouseDragged(MouseEvent e) { x = e.getX(); y = e.getY(); repaint(); } @Override public void mouseMoved(MouseEvent e) { } } |
以上のコードを追加したら、実行してみましょう。
ウィンドウ上でマウスをドラッグしてみて、線が描けたら成功です。
いかがだったでしょうか。
実は、前章までで学んだ内容を応用すれば、テキストフィールドに数字を入力することでブラシサイズを変更したり、スライダーを動かしてブラシの色を変更することは比較的簡単にできます。
ある程度発展的な内容になりますが、ボタンを付けて画像を読み込んだり、描いた画像を保存したりすることも可能になります。
時間を計測するActionListenerを使えば、簡単なゲームを作ることすら可能です。
また、今回きちんと触れることができませんでしたが、オブジェクト指向、レイアウトマネージャ、グラフィックコンテクストといったキーワードについて自分なりに調べてみると、理解が深まると思います。
みなさんもぜひ、今回作ったお絵かきソフトを元に、自分なりの機能を付けたプログラムを作ってみてください。
きっとよい勉強になると思います。