Timer描画プログラムの改良版
ざざっと作ったプログラムを翌日眺めてみると
自分が書いたコードなのに「何か変だな」と思えたりします。
毎度、管理人イガジーです。
作っている時は色々な事が頭の中にあり、「熱く」なっているのですが
一晩経つと「冷える=冷静になる」からでしょう。
昨日のタイマーでグラフィックを描画するサンプルも、改めてみると何か変です。
paintで描画するbufferedImage の扱いが、ダブルバッファとして使う予定だったのに
ひとつの図形(パーツ)とするように途中で変更してしまったからです。
(描画を速くしたい気持ちがそうさせたのです)
現状では、一部を他の窓で覆ってはずした場合、隠れていた部分が元に
戻らないので、やっぱりダブルバッファにする事にします。
そして、動かす際に移動量を含めた大きな範囲をクリアしてましたが
移動前に消して、移動後に描画すれば、すっきりします。
という訳で、改良したプログラムを掲載しておきます。
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;
public class AnimationTest {
final int bww=30, bhh=30;
final int bufw=200,bufh=170;
BufferedImage b=new BufferedImage(bufw+bww,bufh+bhh,BufferedImage.TYPE_INT_RGB);
final int speed=7;
final int interval=50; //ms
int x,y;
Frame f;
MyCanvas cv;
Timer tmr;
boolean done=false;
int busycount=0;
AnimationTest() { // constructor
f=new Frame("AnimationTest");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev) {
System.exit(0);
}
});
cv=new MyCanvas();
f.add(cv,BorderLayout.CENTER);
Button stpbtn=new Button("Stop");
stpbtn.addActionListener(new TimStop());
f.add(stpbtn,BorderLayout.SOUTH);
tmr=new Timer();
tmr.schedule(new MyTimer(), 1000, interval);
f.setSize(300,300);
f.setVisible(true);
}
class MyTimer extends TimerTask {
int vx=speed;
int vy=2;
public void run() {
if (done) {
cv.g.setColor(Color.BLACK);
cv.g.fillRect(x, y, bww, bhh);
// cv.g.fillRect(0, 0, bww+bufw, bhh+bufh);
x+=vx;
y+=vy;
if ((x<=10)||(x>=bufw)) vx=-vx;
if ((y<=40)||(y>=bufh)) vy=-vy;
cv.g.setColor(Color.YELLOW);
cv.g.fillRect(x, y, bww, bhh);
done=false;
cv.repaint();
}else{
System.out.print("Busy ");
System.out.println(busycount++);
}
}
}
class TimStop implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
tmr.cancel();
}
}
class MyCanvas extends Canvas {
private static final long serialVersionUID = 1L;
// Toolkit tk=Toolkit.getDefaultToolkit();
Graphics g;
MyCanvas() {
x=10;
y=40;
g=b.getGraphics();
// this.setBackground(Color.BLACK);
}
@Override
public void update(Graphics g0){
paint(g0);
}
@Override
public void paint(Graphics g0) {
g0.drawImage(b,0,0,f);
// tk.sync();
done=true;
}
}
public static void main(String[] args) {
new AnimationTest();
}
}
タイマールーチンにも、再入保護を入れました。
描画は思ってたよりも速くて、50ms毎(20fps)に追随してるように見えます。
(気のせいかもしれませんが)
これを下敷きにして試してみると、色々な発見がありそうです。
Toolkitにsync()というメソッドがあるのですが、上記ソースではコメントにしています。
管理人イガジーの環境では、ざっと見ですが、入れても入れなくても
動作に違いは無いように見えました(もう少し遊んでみます)。
この記事へのコメントはこちら