生物屋さんのためのゼロからのプログラミング

―忘れないための覚書 (たま~に更新)―

ウインドウサイズを変えても、描画が消えない方法

GraphicsのdrawOvalやdrawLineで円や直線を描画しても、ウインドウサイズを変えると描画が消えてしまうので、Graphics2Dを用いてウインドウサイズを変えても描画が消えない方法を書いた。

import java.awt.Color;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GraphicTest extends JFrame implements ActionListener {

	BufferedImage img;
	JFrame imgFrame;
	MyPane mypane;
	int counter = 0;

	//画像ファイルを開く
	public void Open () {
		imgFrame = new JFrame ("Test");
		imgFrame.setBounds (100, 100, 300, 200);
		imgFrame.setVisible(true);

		try {
			img = ImageIO.read(new File ("開きたい画像"));
		} catch (IOException ex) {
			System.out.println("Open Miss");
		}

		mypane = new MyPane(300, 200);
		imgFrame.getContentPane().add(mypane);

	}

	//線を増やす
	public void roi() {
		counter++;
		mypane.repaint();
	}

	//保存ダイアログを使用せずに保存
	public void save () {
		try {
			ImageIO.write(img, "png", new File ("保存先"));
		} catch (Exception ex) {
			System.out.println("save Miss");
		}
	}

	//保存ダイアログを使用して保存
	public void saveName () {
		try {
			FileOutputStream fo = new FileOutputStream (this.writeFile());
			ImageIO.write(img, "png", fo);
		} catch (IOException ex) {
			System.out.println("Miss");
		}
	}

	//出力画像の名前書き
	String writeFile () {
		FileDialog fd = new FileDialog (new Frame (), "保存", FileDialog.SAVE);
		fd.setVisible(true);
		String fullpath = fd.getDirectory() + fd.getFile();
		fd.dispose();
		return fullpath;
	}


	//画像を貼る用のツール
	public class MyPane extends JPanel {
		public MyPane (int width, int height) {
			setSize (width, height);
		}

		public void paintComponent (Graphics g) {
			Graphics2D g2 = (Graphics2D)g;
			g2.drawImage(img, 0, 0, this);

			Graphics2D rg = img.createGraphics();

			BasicStroke bs = new BasicStroke(5.0f);
			rg.setStroke(bs);

			if (counter < 5) {
			        rg.setPaint(Color.green);
			} else if (counter >= 5 && counter < 10) {
				rg.setPaint(Color.blue);
			} else {
				rg.setPaint(Color.red);
			}
			rg.draw(new Line2D.Double(70 + counter * 10, 40 + counter * 10, 50 + counter * 20, 100 + counter * 20));
		}
	}

	public void actionPerformed (ActionEvent e) {
		String cmd = e.getActionCommand();
		if (cmd.equals("open") ) {
			Open();
		} else if (cmd.equals("roi")) {
			roi();
		} else if (cmd.equals("save")) {
			save();
		} else if (cmd.equals("save2")) {
			saveName();
		}
 	}

	GraphicTest() {
		JButton button = new JButton ("Open");
		JButton roiB = new JButton ("ROI");
		JButton saveB = new JButton ("Save");
		JButton saveB2 = new JButton ("Save2");
		button.addActionListener(this);
		roiB.addActionListener (this);
		saveB.addActionListener(this);
		saveB2.addActionListener(this);
		button.setActionCommand("open");
		roiB.setActionCommand("roi");
		saveB.setActionCommand("save");
		saveB2.setActionCommand("save2");
		JPanel pane = new JPanel ();
		pane.add(button);
		pane.add(roiB);
		pane.add(saveB);
		pane.add(saveB2);
		getContentPane().add(pane);
	}

	public static void main(String[] args) {
		GraphicTest frame = new GraphicTest();
		frame.setBounds (100, 100, 100, 110);
		frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}

ここでは、JPanelを継承した"MyPane"のクラス内に描画用のメソッドを入れた。

       Graphics2D rg = img.createGraphics();

の部分で、BufferedImageからGraphics2Dオブジェクトを取得し、このGraphics2Dに対して線を描いた。

また、保存方法として保存ダイアログを使用しない方法 (save())(左図) と、保存ダイアログを使用した方法 (saveName()) (右図)を書いた。(区別するため、save()とsaveName()の間でroi()で線を増やしている。)
f:id:Aki-Miya:20150422212554p:plain

この方法で、ウインドウサイズを変えると描画が消えず、さらに描画もきちんと保存されることが確認できた。