プロ2 > 資料 > 第4章
第4章:自前のクラスを作る
目標
4.1 図形のクラス定義
従来の手続き的な図形の描画(非推奨)
import java.awt.*;
import javax.swing.*;
public class Sample41a extends JPanel {
Color col1 = Color.MAGENTA, col2 = Color.BLUE;
int xpos1 = 100, xpos2 = 190;
int ypos1 = 50, ypos2 = 90;
int rad1 = 30, rad2 = 40;
public void paintComponent(Graphics g) {
g.setColor(col1);
g.fillOval(xpos1 - rad1, ypos1 - rad1, rad1 * 2, rad1 * 2);
g.setColor(col2);
g.fillOval(xpos2 - rad2, ypos2 - rad2, rad2 * 2, rad2 * 2);
}
public static void main(String[] args) {
JFrame app = new JFrame();
app.add(new Sample41a());
app.setSize(400, 300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
}
- 描画の詳細がpaintComponentメソッドに記述されている.2つの円を描画していることがわかりにくい.
- 2つの円の変数がまとめて定義されており,区別しにくい.円の数が多くなると扱いにくくなる.
オブジェクト指向的な図形の描画
import java.awt.*;
import javax.swing.*;
public class Sample41 extends JPanel {
Circle c1 = new Circle(Color.MAGENTA, 100, 50, 30);
Circle c2 = new Circle(Color.BLUE, 190, 90, 40);
public void paintComponent(Graphics g) {
c1.draw(g);
c2.draw(g);
}
public static void main(String[] args) {
JFrame app = new JFrame();
app.add(new Sample41());
app.setSize(400, 300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
static class Circle {
Color col;
int xpos, ypos, rad;
public Circle(Color c, int x, int y, int r) {
col = c;
xpos = x;
ypos = y;
rad = r;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2);
}
}
}
- 円をCircleという名の1つのクラスとして表現している.クラスは変数とオブジェクトを操作するメソッド(関数)から構成されている.
- コンストラクタはクラス名をメソッド名とする特別なメソッドで,オブジェクトが生成(new)されると呼び出される.オブジェクトの初期化のために利用される.
- 手続き型プログラムと比べると,1つの図形が1つのオブジェクト変数として表現されており,2つの円を描画していることがわかりやすい.
- クラスCircleを定義することで,内部のデータ構造がカプセル化され,情報が隠蔽されているので,バグが出にくい.プログラムの拡張も容易である.
複数のクラスの定義
import java.awt.*;
import javax.swing.*;
public class Ex41cd extends JPanel {
Circle c1 = new Circle(Color.MAGENTA, 100, 50, 30);
Circle c2 = new Circle(Color.BLUE, 180, 120, 40);
Rect r1 = new Rect(Color.YELLOW, 200, 80, 80, 50);
Triangle t1 = new Triangle(Color.BLACK, 50, 120, 200, 80, 180, 20);
public void paintComponent(Graphics g) {
c1.draw(g);
c2.draw(g);
r1.draw(g);
t1.draw(g);
}
public static void main(String[] args) {
JFrame app = new JFrame();
app.add(new Ex41cd());
app.setSize(400, 300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
static class Circle {
Color col;
int xpos, ypos, rad;
public Circle(Color c, int x, int y, int r) {
col = c;
xpos = x;
ypos = y;
rad = r;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2);
}
}
static class Rect {
Color col;
int xpos, ypos, width, height;
public Rect(Color c, int x, int y, int w, int h) {
col = c;
xpos = x;
ypos = y;
width = w;
height = h;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillRect(xpos - width / 2, ypos - height / 2, width, height);
}
}
static class Triangle {
Color col;
int[] xs, ys;
public Triangle(Color c, int x0, int y0, int x1, int y1, int x2, int y2) {
col = c;
xs = new int[] { x0, x1, x2 };
ys = new int[] { y0, y1, y2 };
}
public void draw(Graphics g) {
g.setColor(col);
g.fillPolygon(xs, ys, 3);
}
}
}
- 長方形と三角形のクラスを追加している.描画メソッドの名前(ここではdraw))を統一しておくと,オブジェクトの種類が増えても同じように扱える.
4.2 複合図形を組み立てる
import java.awt.*;
import javax.swing.*;
public class Sample42 extends JPanel {
Flag f1 = new Flag(Color.GREEN, Color.WHITE, 30, 100, 80);
Flag f2 = new Flag(Color.GRAY, Color.RED, 20, 240, 120);
public void paintComponent(Graphics g) {
f1.draw(g);
f2.draw(g);
}
public static void main(String[] args) {
JFrame app = new JFrame();
app.add(new Sample42());
app.setSize(400, 300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
static class Flag {
Rect r1;
Circle c1;
public Flag(Color cl1, Color cl2, int r, int x, int y) {
r1 = new Rect(cl1, x, y, r * 6, r * 4);
c1 = new Circle(cl2, x, y, r);
}
public void draw(Graphics g) {
r1.draw(g);
c1.draw(g);
}
}
static class Circle {
Color col;
int xpos, ypos, rad;
public Circle(Color c, int x, int y, int r) {
col = c;
xpos = x;
ypos = y;
rad = r;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2);
}
}
static class Rect {
Color col;
int xpos, ypos, width, height;
public Rect(Color c, int x, int y, int w, int h) {
col = c;
xpos = x;
ypos = y;
width = w;
height = h;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillRect(xpos - width / 2, ypos - height / 2, width, height);
}
}
}
- 円(Circle)と長方形(Rect)を部品としてフラグ(Flag)を定義している.
4.3 マウスで図形を移動させる
(無名クラスを用いた)アダプタの登録
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Sample43 extends JPanel {
Circle c1 = new Circle(Color.RED, 100, 50, 30);
Circle c2 = new Circle(Color.BLUE, 150, 90, 40);
public Sample43() {
setOpaque(false);
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent evt) {
c1.moveTo(evt.getX(), evt.getY());
repaint();
}
});
}
public void paintComponent(Graphics g) {
c1.draw(g);
c2.draw(g);
}
public static void main(String[] args) {
JFrame app = new JFrame();
app.add(new Sample43());
app.setSize(400, 300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
static class Circle {
Color col;
int xpos, ypos, rad;
public Circle(Color c, int x, int y, int r) {
col = c;
xpos = x;
ypos = y;
rad = r;
}
public void moveTo(int x, int y) {
xpos = x;
ypos = y;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2);
}
}
}
- オブジェクトがマウスやキーボードなどのイベントを使えるようにするには,それに対応するインタフェースを実装したアダプタを登録する必要がある.アダプタオブジェクト(MouseMotionAdaptor)を無名クラスとして,addMouseMotionListenerメソッドを用いてオブジェクトに登録する.
- アダプタ内のメソッド名は決められたものだけが定義できる.
- 簡単なインタフェースの説明は教科書p.75にある.
個別にクラス定義したアダプタの登録
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Sample43a extends JPanel {
Circle c1 = new Circle(Color.RED, 100, 50, 30);
Circle c2 = new Circle(Color.BLUE, 150, 90, 40);
public Sample43a() {
setOpaque(false);
addMouseMotionListener(new MyAdapter1());
}
class MyAdapter1 extends MouseMotionAdapter {
public void mouseDragged(MouseEvent evt) {
c1.moveTo(evt.getX(), evt.getY());
repaint();
}
}
public void paintComponent(Graphics g) {
c1.draw(g);
c2.draw(g);
}
public static void main(String[] args) {
JFrame app = new JFrame();
app.add(new Sample43a());
app.setSize(400, 300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
static class Circle {
Color col;
int xpos, ypos, rad;
public Circle(Color c, int x, int y, int r) {
col = c;
xpos = x;
ypos = y;
rad = r;
}
public void moveTo(int x, int y) {
xpos = x;
ypos = y;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2);
}
}
}
- MyAdapter1という名のクラスとして,マウス用アダプタを定義している.
- マウスで複雑な動作をしたり,幾つもの場所でマウスを使う場合はこちらのほうが良い.
ykitamura@kwansei.ac.jp