畫出每一幀:
剩下的就是將每一幀圖象繪出。在上例中調用了applet的repaint()來繪出每一幀圖象。
public void paint(Graphics g) {
g.setColor(Color.black);
g.drawString("Frame " + frame, 0, 30);
}
生成圖形:
現在我們來畫一些稍微困難的東西。下例畫了一個正弦曲線的組合, 對於每一個x,畫一條短的垂直線,所有這些線組成了一個圖形,並且每幀變化。
但不幸有些閃動,在以後我們將解釋為什麼閃以及怎樣避免。
public void paint(Graphics g) {
Dimension d = size();
int h = d.height / 2;
for (int x = 0 ; x < d.width; x++) {
int y1 = (int)((1.0 + Math.sin((x - frame)*0.05))*h);
int y2 = (int)((1.0 + math.sin((x + frame)*0.05))*h);
g.DrawLine(x, y1, x, y2);
}
}
避免閃爍:
上例中的閃爍有兩個原因:繪制每一幀花費的時間太長(因為重繪時要求的計算量大),二是在每次調用pait()前整個背景被清除,當在進行下一幀的計算時,用戶看到的是背景。
清除背景和繪制圖形間的短暫時間被用戶看見,就是閃爍。在有些平台如PC機上閃爍比在X Window上明顯,這是因為X Window的圖象被緩存過,使得閃爍的時間比較短。
有兩種辦法可以明顯地減弱閃爍:重載update()或使用雙緩沖。
重載update()?
當AWT接收到一個applet的重繪請求時,它就調用applet的update()。
缺省地,update()清除applet的背景,然後調用paint()。重載update(),將以前在paint()中的繪圖代碼包含在update()中,從而避免每次重繪時將整個區域清除。
既然背景不在自動清除,我們需要自己在update()中完成。我們在繪制新的線之前獨自將豎線擦除,完全消除了閃爍。
public void paint(Graphics g) {
update(g);
}
public void update(Graphics g) {
Color bg = getBackground();
Dimension d = size();
int h = d.height / 2;
for (int x = 0; x < d.width; x++) {
int y1 = (int)((1.0 + Math.sin((x - frame)*0.05))*h);
int y2 = (int)((1.0 + Math.sin((x + frame)*0.05))*h);
if (y1 > y2) {
int t = y1;
y1 = y2;
y2 = t;
}
g.setColor(bg);
g.drawLine(x, 0, x, y1);
g.drawLine(x, y2, x, d.height);
g.setColor(Color.black);
g.drawLine(x, y1, x, y2);
}