Swingでいろいろ作ってみる

# Swingでいろいろ作ってみます

# 事前学習とまとめ

http://wisdom.sakura.ne.jp/system/java/awt/Gjava8.html

```Java
repaint();
```
を実行することで

1. paint()を再度呼び出し

を実行します。
背景色のぬりつぶしをなくすにはupdate()をオーバーライドして

```Java
public void update(Graphics g) {
	paint(g);
}
```
に変更するらしい。

マウスイベントは抽象クラスMouseListenerに対し処理内容を記述すればよい。ただし、抽象クラスのためすべて定義が必要。

```Java
public void mousePressed(MouseEvent me) {} 
    public void mouseClicked(MouseEvent me) {}
    public void mouseEntered(MouseEvent me) {}
    public void mouseExited(MouseEvent me) {}
    public void mouseReleased(MouseEvent me) {}
```

https://www.javadrive.jp/tutorial/event/index3.html


## Timerオブジェクト

https://teratail.com/questions/78033

https://techacademy.jp/magazine/22245

よくわかりませんが、mainの処理は止まるのでしょうか？

ー＞止まりません
main内でscheduleで設定後、次の文に移動します。Timerタスクは別で割り込み処理のように実行されます。

初期設定

```Java
Timer time = new Timer();
time.scheduleAtFixedRate(new SampleTask(), delay, period);
```
実行内容

```Java
public class SampleTask extends TimerTask {
    public void run() {
       
    }
}
```

repaint()を頻繁に呼び出せば動的な画面が作れます。

cancel()でタイマーを終了することができる

# アニメーション：徐々に大きくなる正方形
Timerオブジェクト：repaintを起動
Flameオブジェクト：フレームを作る
    <-このクラス内でmainを記述
    <-paint();を書く

https://java-beginner.com/swing-draw/

Timerオブジェクト：repaintを起動
をするには、Timerオブジェクトにフレームのインスタンスを渡す必要があります。

TimerクラスとTimerTaskクラス
の二つがある
* Timerクラスはスケジュールを設定するのみ
* TimerTaskクラスは実行内容を定義する

TimerTaskはcancel()で停止
Timerはdispose()で終了ー＞これを止めないとプログラムが終わらない

経過時間を取得

```Java
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;      //msで経過時間を取得
```

# ダブルバッファ
アニメーション表示をさせると、画面のちらつきが問題になります。これは描画する要素が増えると全要素の描画が終わる前に一度表示され、描画が追加され表示が完了という流れが起きることに起因します。
対策としてはダブルバッファを入れることで全描画が完了してから表示させるという方法を取ります。

http://hp.vector.co.jp/authors/VA012735/java/dbuf1.htm

```java
Image imgBuf = createImage(width,hight);
Graphics gBuf = imgBuf.getGraphics(); gBuf.fillRect(0,0,width,hight);

/*
描画処理
*/

Graphics graphics = getContentPane().getGraphics();
graphics.drawImage(imgBuf,0,0,this);
```

これでダブルバッファできます。

# サンプル1:波紋生成
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/8f1482a4-50fe-5370-d4aa-8f1ba5642593.png)

ランダムで円を描画し、リアルタイムでサイズを大きくしていきます。
まだまだオブジェクト指向がよくわかっていません。
動作の流れは

1. フレームを作成
1. タイマーを仕掛ける
1. タイマーの呼び出しで描画（+波紋のインスタンス内のdrawメソッド呼び出し）
1. 各画面作成時、特定の確率で波紋のインスタンスを生成


```java:Flame.java
import javax.swing.*;
import java.awt.*;
import java.util.Random;
import java.util.Timer;

public class Flame extends JFrame {
    long startTime;
    int hight = 500;
    int width = 500;

    WaterRipple[] ripples = new WaterRipple[100];
    int ripples_num = 0;

    public static void main(String[] args) {
        System.out.println("Start");
        Flame frame = new Flame();
        java.util.Timer timer = new Timer();
        Timer_task timer_task = new Timer_task();
        timer_task.setFlame(frame);
        timer_task.setTimer(timer);
        timer.scheduleAtFixedRate(timer_task, 0,30);

    }

    public Flame() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(width, hight);
        setVisible(true);
        startTime = System.currentTimeMillis();
    }

    public void paint(Graphics g){
        Image imgBuf = createImage(width,hight);
        Graphics gBuf = imgBuf.getGraphics();
        gBuf.setColor(Color.white);
        gBuf.fillRect(0,0,width,hight);
        long now_time = System.currentTimeMillis();

        //10%の確率で波紋を生成
        Random rand = new Random();
        int probability = rand.nextInt(99);
        if(probability<10){
            ripples[ripples_num] = new WaterRipple(width,hight,now_time);
            ripples_num++;
        }

        //波紋を描画
        for(int i = 0;i<ripples_num;i++ ){
            if(ripples[i].drawable == true) {
                ripples[i].calculate_radius(now_time);
                ripples[i].draw(gBuf);
            }
        }
        Graphics graphics = getContentPane().getGraphics();
        graphics.drawImage(imgBuf,0,0,this);

        System.out.println(ripples_num);

    }
}
```

```java:Timer_task.java
import java.util.Timer;
import java.util.TimerTask;

public class Timer_task extends TimerTask {
    Flame frame_timer;
    int num = 0;
    Timer time2;

    public void run() {
        frame_timer.repaint();
        num++;

        if(num>1000){
            System.out.println("End");
            cancel();
            frame_timer.dispose();
            time2.cancel();
        }
    }
    public void setFlame(Flame frame){
        frame_timer = frame;
    }
    public void setTimer(Timer time3){
        this.time2 = time3;
    }
}
```

```java:WaterRipple.java
import java.awt.*;
import java.util.Random;

public class WaterRipple {
    int x;
    int y;
    int radius = 0;
    long start_time;
    Color color;
    boolean drawable = true;
    int height;
    int width;

    public WaterRipple(int width,int height,long start_time){
        Random rand = new Random();
        this.x = rand.nextInt(width);
        this.y = rand.nextInt(height);
        this.height = height;
        this.width = width;
        this.start_time = start_time;
        color = new Color(rand.nextInt(250),rand.nextInt(250),rand.nextInt(250));
    }

    public void calculate_radius(long now_time){
        radius = (int) ((now_time-start_time)*0.05);
        if(radius>width || radius> height){
            this.drawable = false;
        }
    }

    public void draw(Graphics g){
        g.setColor(color);
        g.fillOval(x-radius,y-radius,radius*2,radius*2);
    }
}
```

初めてにしては割と頑張ったと思います。