arc の日記

はてなダイアリーから引っ越してきました。さらに新しい記事は https://junkato.jp/ja/blog/ で書いています。

とりあえずウィンドウを表示して何かしたいとき使う基底クラスAbstractFrame

AbstractFrame

Java2Dを使って画面に何か出したいと思ったとき、適当なサイズのJFrameを作ってJPanel突っ込んでpaint(Graphics g)を実装して…という一連の流れが面倒なので、下記のようなabstract classを作っておいて、実際の場面ではこれをextendsして使ってます。

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;

import javax.swing.JComponent;
import javax.swing.JFrame;


/** 単なるウィンドウ */
public abstract class AbstractFrame extends JFrame {
	private static final long serialVersionUID = 1L;
	private JComponent component;

	/** 初期化処理 */
	public void initialize(int width, int height) {

		// パネルの初期化
		component = new MainComponent();
		getContentPane().add(component);

		// メインウィンドウの初期化
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		setResizable(false);
		setVisible(true);
		final Insets insets = getInsets();
		setSize(width+insets.left+insets.right, height+insets.top+insets.bottom);
	}

	/** 終了処理 */
	public void dispose() {
		System.exit(0);
	}

	/** 描画処理 */
	public abstract void paint2D(Graphics2D g);

	/** 再描画の要請 */
	public void requestRepaint() {
		if (component != null)
			component.repaint();
	}

	/** 描画領域 */
	class MainComponent extends JComponent {
		private static final long serialVersionUID = 1L;
		public void paint(Graphics g) {
			paint2D((Graphics2D) g);
		}
		public void update(Graphics g) { paint(g); }
	}
}

この抽象クラスを継承したクラスでpaint2D(Graphics2D g)を実装して使います。画面の表示を更新したいときはrequestRepaint()を呼びます。

Javaでデジタル時計

使用例; 文字だけの時計。

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;

import javax.swing.SwingUtilities;
import javax.swing.Timer;


public class SamplePaint extends AbstractFrame implements ActionListener {

	public static void main(String[] args) {

		// Swingがらみの処理はEvent Dispatch Thread上でやる
		SwingUtilities.invokeLater(new Runnable() {
			public void run() { new SamplePaint(); }
		}

	}

	public SamplePaint() {
		initialize(320, 240);
		new Timer(1000, this).start();
	}

	@Override
	public void paint2D(Graphics2D g) {
		g.setColor(Color.white);
		g.fillRect(0, 0, getWidth()-1, getHeight()-1);
		g.setColor(Color.black);
		final Calendar now = Calendar.getInstance();
		final int
			h = now.get(Calendar.HOUR_OF_DAY),
			m = now.get(Calendar.MINUTE),
			s = now.get(Calendar.SECOND);
		g.drawString(""+h+":"+m+":"+s, 30, 30);
	}

	@Override
	public void actionPerformed(ActionEvent actionevent) {
		requestRepaint();
	}

}

initialize(int width, int height)に渡すのは描画領域の幅と高さです。ウィンドウ自体は、枠がある分、それより大きくなります。ウィンドウを閉じるボタンが押されるとプログラムが終了します。
SwingのTimerが発火するたびrequestRepaint()を呼んでいます。その中でpaint2D(Graphics2D g)が呼ばれ、時計の表示が更新されます。

…まぁ、これだけならProcessing使えばいいんですけどね。あ、最近ではJavaFXもあるか。