緊急描画


すぐに描画処理をする

Swing コンポーネントの描画は単一のイベントディスパッチスレッドからアクセスされ
それ以外のスレッドからアクセスできないということは以前説明しました

そのため、一般的な Swing アプリケーションでは
イベントディスパッチスレッドから repaint() を呼び出してイベントに対応した描画処理を行い
アニメーションなどは SwingUtilities を利用して別スレッドから行います

しかし、イベントディスパッチスレッドで repaint() を呼び出した場合
そのイベントハンドラが終了するまで描画されないということに注意してください

もちろん、イベントディスパッチスレッドは単一なので
イベントハンドラメソッドは、描画に関係ない処理は他のスレッドに行わせ
できる限り最小の処理で制御を返すことがもっとも理想的なプログラムです

このため、repaint() は即座に呼び出されるわけではなく
現在のイベントハンドラメソッドが制御を返すのを待つことになります
もし、メソッドを呼び出すと同じに描画を行う特別な必要があるならば
JComponent クラスの paintImmediately() メソッドという手段があります

public void paintImmediately(int x , int y , int w , int h)
public void paintImmediately(Rectangle r)

このメソッドは、コンポーネントの指定矩形を即座に再描画します
x と y には、始点 X 座標及び Y 座標を、w には横幅、h には高さを指定します
r には長方形をあらわす Rectangle オブジェクトを指定します

不要な描画は省略されるべきであり、repaint() はそれに適っています
しかし、イベント処理中に描画処理を行いたい場合、repaint() では実現できません
そこで、このメソッドを使用します
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Test extends JApplet implements ActionListener {
	JPanel jpl = new JPanelEx();
	public void init() {
		Container contentPane = getContentPane();
		contentPane.setLayout(new FlowLayout());

		Button bt1 = new Button("paintImmediately");
		Button bt2 = new Button("repaint");
		bt1.addActionListener(this);
		bt2.addActionListener(this);

		jpl.setPreferredSize(new Dimension(200 , 200));

		contentPane.add(bt1);
		contentPane.add(bt2);
		contentPane.add(jpl);
	}
	
	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals("repaint")) jpl.repaint();
		else jpl.paintImmediately(50 , 50 , 100 , 100);

		try { Thread.sleep(3000); }
		catch(Exception err) {}
	}

	class JPanelEx extends JPanel {
		int backColor = 0xFF0000;
		public void paint(Graphics g) {
			backColor = backColor == 0xFF0000 ? 0xFF : 0xFF0000;
			Dimension dim = getSize();
			g.setColor(new Color(backColor));
			g.fillRect(0 , 0 , dim.width , dim.height);
		}
	}
}


JPanelEx は、描画されるごとに赤と青に色を切り替えながら自分を塗りつぶします
ボタンを押すと、それぞれ再描画メソッドを実行したあとに
時間のかかる処理をエミュレートした Thread.sleep() によってスレッドが停止します

paintImmediately ボタンを押すと、すぐにパネルは再描画され
その後に待ちが入りますが、repaint() を呼び出した場合は
待ちが終了してイベントハンドラメソッドが制御を返すまで再描画されません



前のページへ戻る次のページへ