본문 바로가기
솔루션모음/파워자바 프로그래밍

[파워자바] 23장 프로그래밍 솔루션 답지

by 이얏호이야호 2023. 2. 16.

1.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DecimalFormat;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class SecondCounterDemo extends JPanel {
	private SecondCounterRunnable sc = new SecondCounterRunnable();

	private JButton startB = new JButton("카운터 시작");

	private JButton stopB = new JButton("카운터 중지");

	public SecondCounterDemo() {
		stopB.setEnabled(false);

		startB.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				startB.setEnabled(false);

				Thread counterThread = new Thread(sc, "Counter");
				counterThread.start();

				stopB.setEnabled(true);
				stopB.requestFocus();
			}
		});

		stopB.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				stopB.setEnabled(false);
				sc.stopClock();
				startB.setEnabled(true);
				startB.requestFocus();
			}
		});

		JPanel innerButtonP = new JPanel();
		innerButtonP.setLayout(new GridLayout(0, 1, 0, 3));
		innerButtonP.add(startB);
		innerButtonP.add(stopB);

		JPanel buttonP = new JPanel();
		buttonP.setLayout(new BorderLayout());
		buttonP.add(innerButtonP, BorderLayout.NORTH);

		this.setLayout(new BorderLayout(10, 10));
		this.setBorder(new EmptyBorder(20, 20, 20, 20));
		this.add(buttonP, BorderLayout.WEST);
		this.add(sc, BorderLayout.CENTER);
	}

	public static void main(String[] args) {
		SecondCounterDemo scm = new SecondCounterDemo();

		JFrame f = new JFrame();
		f.setContentPane(scm);
		f.setSize(320, 200);
		f.setVisible(true);
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
	}

	class SecondCounterRunnable extends JComponent implements Runnable {
		private volatile boolean keepRunning;

		private Font paintFont = new Font("SansSerif", Font.BOLD, 14);

		private volatile String timeMsg = "never started";

		private volatile int arcLen = 0;

		public SecondCounterRunnable() {
		}

		public void run() {
			runClock();
		}

		public void runClock() {
			DecimalFormat fmt = new DecimalFormat("0.000");
			long normalSleepTime = 100;

			int counter = 0;
			keepRunning = true;

			while (keepRunning) {
				try {
					Thread.sleep(normalSleepTime);
				} catch (InterruptedException x) {
				}
				counter++;
				double counterSecs = counter / 10.0;
				timeMsg = fmt.format(counterSecs);
				arcLen = (((int) counterSecs) % 60) * 360 / 60;
				repaint();
			}
		}

		public void stopClock() {
			keepRunning = false;
		}

		public void paint(Graphics g) {
			g.setColor(Color.black);
			g.setFont(paintFont);
			g.drawString(timeMsg, 0, 15);

			g.fillOval(0, 20, 100, 100);

			g.setColor(Color.white);
			g.fillOval(3, 23, 94, 94);

			g.setColor(Color.red);
			g.fillArc(2, 22, 96, 96, 90, -arcLen);
		}
	}

}

3.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

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

public class ScrollText extends JComponent {
	private BufferedImage image;
	private Dimension imageSize;
	private volatile int currOffset;
	private Thread internalThread;
	private volatile boolean noStopRequested;

	public ScrollText(String text) {
		currOffset = 0;
		buildImage(text);

		setMinimumSize(imageSize);
		setPreferredSize(imageSize);
		setMaximumSize(imageSize);
		setSize(imageSize);

		noStopRequested = true;
		Runnable r = new Runnable() {
			public void run() {
				try {
					runWork();
				} catch (Exception x) {
					x.printStackTrace();
				}
			}
		};

		internalThread = new Thread(r, "ScrollText");
		internalThread.start();
	}

	private void buildImage(String text) {
		RenderingHints renderHints = new RenderingHints(
				RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);

		renderHints.put(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);

		BufferedImage scratchImage = new BufferedImage(1, 1,
				BufferedImage.TYPE_INT_RGB);

		Graphics2D scratchG2 = scratchImage.createGraphics();
		scratchG2.setRenderingHints(renderHints);

		Font font = new Font("Serif", Font.BOLD | Font.ITALIC, 24);

		FontRenderContext frc = scratchG2.getFontRenderContext();
		TextLayout tl = new TextLayout(text, font, frc);
		Rectangle2D textBounds = tl.getBounds();
		int textWidth = (int) Math.ceil(textBounds.getWidth());
		int textHeight = (int) Math.ceil(textBounds.getHeight());

		int horizontalPad = 10;
		int verticalPad = 6;

		imageSize = new Dimension(textWidth + horizontalPad, textHeight
				+ verticalPad);

		image = new BufferedImage(imageSize.width, imageSize.height,
				BufferedImage.TYPE_INT_RGB);

		Graphics2D g2 = image.createGraphics();
		g2.setRenderingHints(renderHints);

		int baselineOffset = (verticalPad / 2) - ((int) textBounds.getY());

		g2.setColor(Color.white);
		g2.fillRect(0, 0, imageSize.width, imageSize.height);

		g2.setColor(Color.blue);
		tl.draw(g2, 0, baselineOffset);

		scratchG2.dispose();
		scratchImage.flush();
		g2.dispose();
	}

	public void paint(Graphics g) {
		g.setClip(0, 0, imageSize.width, imageSize.height);

		int localOffset = currOffset;
		g.drawImage(image, -localOffset, 0, this);
		g.drawImage(image, imageSize.width - localOffset, 0, this);

		g.setColor(Color.black);
		g.drawRect(0, 0, imageSize.width - 1, imageSize.height - 1);
	}

	private void runWork() {
		while (noStopRequested) {
			try {
				Thread.sleep(100);

				currOffset = (currOffset + 1) % imageSize.width;

				repaint();
			} catch (InterruptedException x) {
				Thread.currentThread().interrupt();
			}
		}
	}

	public void stopRequest() {
		noStopRequested = false;
		internalThread.interrupt();
	}

	public boolean isAlive() {
		return internalThread.isAlive();
	}

	public static void main(String[] args) {
		ScrollText st = new ScrollText("우리는 스레드로 애니메이션을 할 수 있어요!");

		JPanel p = new JPanel(new FlowLayout());
		p.add(st);

		JFrame f = new JFrame("ScrollText Demo");
		f.setContentPane(p);
		f.setSize(400, 100);
		f.setVisible(true);
	}
}

 

 

4.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

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

public class SwingWithThread extends JComponent {
	private Image[] frameList;

	private long msPerFrame;

	private volatile int currFrame;

	private Thread internalThread;

	private volatile boolean noStopRequested;

	public SwingWithThread(int width, int height, long msPerCycle,
			int framesPerSec, Color fgColor) {

		setPreferredSize(new Dimension(width, height));

		int framesPerCycle = (int) ((framesPerSec * msPerCycle) / 1000);
		msPerFrame = 1000L / framesPerSec;

		frameList = buildImages(width, height, fgColor, framesPerCycle);
		currFrame = 0;

		noStopRequested = true;
		Runnable r = new Runnable() {
			public void run() {
				try {
					runWork();
				} catch (Exception x) {
					// in case ANY exception slips through
					x.printStackTrace();
				}
			}
		};

		internalThread = new Thread(r);
		internalThread.start();
	}

	private Image[] buildImages(int width, int height, Color color, int count) {

		BufferedImage[] im = new BufferedImage[count];

		for (int i = 0; i < count; i++) {
			im[i] = new BufferedImage(width, height,
					BufferedImage.TYPE_INT_ARGB);

			double xShape = ((double) (i * width)) / (double) count;
			;
			double yShape = ((double) (i * height)) / (double) count;

			double wShape = 2.0 * (width - xShape);
			double hShape = 2.0 * (height - yShape);
			Rectangle2D shape = new Rectangle2D.Double(xShape, yShape, wShape,
					hShape);

			Graphics2D g2 = im[i].createGraphics();
			g2.setColor(color);
			g2.fill(shape);
			g2.dispose();
		}

		return im;
	}

	private void runWork() {
		while (noStopRequested) {
			currFrame = (currFrame + 1) % frameList.length;
			repaint();

			try {
				Thread.sleep(msPerFrame);
			} catch (InterruptedException x) {
				Thread.currentThread().interrupt();
			}
		}
	}

	public void stopRequest() {
		noStopRequested = false;
		internalThread.interrupt();
	}

	public boolean isAlive() {
		return internalThread.isAlive();
	}

	public void paint(Graphics g) {
		g.drawImage(frameList[currFrame], 0, 0, this);
	}

	public static void main(String[] args) {
		SwingWithThread redSquish = new SwingWithThread(250, 200, 2500L, 10,
				Color.red);
		JFrame f = new JFrame();
		f.setLayout(new FlowLayout());
		f.add(redSquish);

		f.setSize(450, 250);
		f.setVisible(true);
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
	}
}

댓글