The last time I used JFrame / Canvas was during my graduation research at university. After a long time using Java, it's hard to hear what I say ...: sweat_drops:
I'm forgetting how to use Java, so
I would like to write down about JFrame / Canvas as a memorandum instead of rehabilitation: writing_hand:
I would like to make a simple drawing application using the Jframe / Canvas class.
The finished product will look like an image. : art:
First, let's create a window to display the app. Here, JFrame is used. How to use it is like this.
Step1.java
package paintApp;
import javax.swing.JFrame;
public class Step1 {
	static int w = 800, h = 600;
	public static void main(String[] args) {
		run();
	}
	public static void run() {
		//Create an instance of JFrame
		JFrame frame = new JFrame("Drawing app");
		//Exit the program when the window is closed
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//Window size / initial position
		frame.setSize(w, h);
		frame.setLocationRelativeTo(null);
		// setBounds(x, y, w, h);
		//Show window
		frame.setVisible(true);
	}
}
I could easily make a frame: v:
Next, prepare a canvas to actually draw a picture. Java provides a convenient class called the Canvas class. Let's add it to the frame.
Step2.java
package paintApp;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Step2 {
	static int w = 800, h = 600;
	public static void main(String[] args) {
		run();
	}
	public static void run() {
		//Create an instance of JFrame
		JFrame frame = new JFrame("Drawing app");
		//Exit the program when the window is closed
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//Window size / initial position
		frame.setSize(w, h);
		frame.setLocationRelativeTo(null);
		// setBounds(x, y, w, h);
		//Create an instance of PaintCanvas
		PaintCanvas canvas = new PaintCanvas();
		//Add to frame
		JPanel pane = new JPanel();
		frame.getContentPane().add(pane);
		canvas.setPreferredSize(new Dimension(w, h));
		pane.add(canvas);
		//Show window
		frame.setVisible(true);
	}
	//Canvas class
	static class PaintCanvas extends Canvas {
		public PaintCanvas() {
			//Set canvas background to white
			setBackground(Color.white);
		}
		public void paint(Graphics g) {
		}
	}
}
A pure white canvas has appeared.
Let's be able to draw a picture here.
Events such as "mouse clicked" or "drag" are called "events".
There is a convenient class that allows you to get this event.
MouseListener and MouseMotionListener /jp/8/docs/api/java/awt/event/MouseMotionListener.html).
The difference between MouseListener and MouseMotionListener is the type of event you can get.
Let's use it properly according to the type of event you want to use.
This time, I want to use click, drag, and move, so I will use both.
** Events you can get **
| MouseListener | MouseMotionListener | 
|---|---|
| mouseClicked | mouseDragged | 
| mouseEntered | mouseDragged | 
| mouseExited | |
| mousePressed | |
| mouseReleased | 
Let's add these to the canvas.
Step3.java
package paintApp;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Step3 {
	static int w = 800, h = 600;
	public static void main(String[] args) {
		run();
	}
	public static void run() {
		//Create an instance of JFrame
		JFrame frame = new JFrame("Drawing app");
		//Exit the program when the window is closed
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//Window size / initial position
		frame.setSize(w, h);
		frame.setLocationRelativeTo(null);
		// setBounds(x, y, w, h);
		//Create an instance of PaintCanvas
		PaintCanvas canvas = new PaintCanvas();
		//Add to frame
		JPanel pane = new JPanel();
		frame.getContentPane().add(pane);
		canvas.setPreferredSize(new Dimension(w, h));
		pane.add(canvas);
		//Show window
		frame.setVisible(true);
	}
	//Canvas class
	static class PaintCanvas extends Canvas implements MouseListener,
			MouseMotionListener {
		public PaintCanvas() {
			//Set MouseListener / MouseMotionListener
			addMouseListener(this);
			addMouseMotionListener(this);
			//Set canvas background to white
			setBackground(Color.white);
		}
		public void paint(Graphics g) {
		}
		@Override
		public void mouseDragged(MouseEvent e) {
			System.out.println(e);
		}
		@Override
		public void mouseMoved(MouseEvent e) {
		}
		@Override
		public void mouseClicked(MouseEvent e) {
		}
		@Override
		public void mousePressed(MouseEvent e) {
		}
		@Override
		public void mouseReleased(MouseEvent e) {
		}
		@Override
		public void mouseEntered(MouseEvent e) {
		}
		@Override
		public void mouseExited(MouseEvent e) {
		}
	}
}
In this way, you can see that it is responding to mouse operations. : mouse_three_button:
… The stage is now set. From here, let's create a process to draw a picture using the acquired mouse event.
The content gets the coordinates of the start point and the end point when dragged with the mouse, and connects them with a line ... That's it: ok_hand:
To explain in a little more detail, when the MouseDragged event occurs, save the mouse coordinates at that time in a variable. When the same event occurs again, the coordinates saved in the previous process are saved in another variable as the starting point, overwriting the current coordinates. In this way, I draw a line while updating the start point and end point.
Now, every time the mouse is dragged, the line grows little by little, and it looks as if the mouse trajectory is displayed as it is.
By the way, when drawing this line, the style of each line is set to "round" at both ends. If you don't do this, both ends will be square lines, and the joints between the lines will be jagged, resulting in an unattractive picture.
Step4.java
package paintApp;
import java.awt.BasicStroke;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Step4 {
	static int w = 800, h = 600;
	public static void main(String[] args) {
		run();
	}
	public static void run() {
		//Create an instance of JFrame
		JFrame frame = new JFrame("Drawing app");
		//Exit the program when the window is closed
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//Window size / initial position
		frame.setSize(w, h);
		frame.setLocationRelativeTo(null);
		// setBounds(x, y, w, h);
		//Create an instance of PaintCanvas
		PaintCanvas canvas = new PaintCanvas();
		//Add to frame
		JPanel pane = new JPanel();
		frame.getContentPane().add(pane);
		canvas.setPreferredSize(new Dimension(w, h));
		pane.add(canvas);
		//Show window
		frame.setVisible(true);
	}
	//Canvas class
	static class PaintCanvas extends Canvas implements MouseListener,
			MouseMotionListener {
		//BufferedImage that holds the drawing contents
		private BufferedImage cImage = null;
		//Instance for drawing to cImage
		private Graphics2D g2d;
		//Line start and end coordinates
		private int x, y, xx, yy;
		//Drawing mode OR eraser mode
		private int type;
		//Line thickness
		public int width = 1;
		//Line color
		public Color c = Color.black;
		public PaintCanvas() {
			//Initialize coordinates
			x = -1;
			y = -1;
			xx = -1;
			yy = -1;
			type = 0;
			//Set MouseListener / MouseMotionListener
			addMouseListener(this);
			addMouseMotionListener(this);
			//Set canvas background to white
			setBackground(Color.white);
			//Generate a BufferedImage that holds the drawing contents
			cImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
			g2d = (Graphics2D) cImage.getGraphics();
			//Make the background of BufferedImage white
			g2d.setColor(Color.WHITE);
			g2d.fillRect(0, 0, w, h);
			//drawing
			repaint();
		}
		public void paint(Graphics g) {
			//Drawing mode (drawing a line segment)
			if (type == 1) {
				if (x >= 0 && y >= 0 && xx >= 0 && yy >= 0) {
					BasicStroke stroke = new BasicStroke(width,
							BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
					g2d.setStroke(stroke);
					g2d.setColor(c);
					g2d.drawLine(xx, yy, x, y);
				}
				//Eraser mode
			} else if (type == 2) {
				if (x >= 0 && y >= 0 && xx >= 0 && yy >= 0) {
					//Set to a line segment with rounded ends
					BasicStroke stroke = new BasicStroke(50.0f,
							BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
					g2d.setStroke(stroke);
					g2d.setColor(Color.white);
					g2d.drawLine(xx, yy, x, y);
				}
			}
			//Reflect the drawing contents on the canvas
			g.drawImage(cImage, 0, 0, null);
		}
		@Override
		public void mouseDragged(MouseEvent e) {
			//Detects the button being pressed
			if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) {
				//Left button click (drawing mode)
				type = 1;
			}
			if ((e.getModifiers() & MouseEvent.BUTTON2_MASK) != 0) {
				//Middle button click
			}
			if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
				//Right button click (eraser mode)
				type = 2;
			}
			//Set past coordinates as start coordinates
			xx = x;
			yy = y;
			//Set new coordinates as end coordinates
			Point point = e.getPoint();
			x = point.x;
			y = point.y;
			//redraw
			repaint();
		}
		@Override
		public void mouseMoved(MouseEvent e) {
			//Initialize coordinates when dragging is complete
			x = -1;
			y = -1;
			xx = -1;
			yy = -1;
			type = 0;
		}
		@Override
		public void mouseClicked(MouseEvent e) {
		}
		@Override
		public void mousePressed(MouseEvent e) {
			Point point = e.getPoint();
			x = point.x;
			y = point.y;
		}
		@Override
		public void mouseReleased(MouseEvent e) {
		}
		@Override
		public void mouseEntered(MouseEvent e) {
		}
		@Override
		public void mouseExited(MouseEvent e) {
		}
	}
}
Drag with the mouse to draw a line there.
It became like that at once!
The drawing app has been completed!
In the image, three functions have been added: clear canvas, change line thickness, and change line color. This alone is enough to draw.
This is a simplified version, so if you add features here, you can make it a more authentic drawing app: smiley:
The final code is here.
PaintApp.java
package paintApp;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class PaintApp {
	static int w = 800, h = 600;
	public static void main(String[] args) {
		run();
	}
	public static void run() {
		//Create an instance of JFrame
		JFrame frame = new JFrame("Drawing app");
		//Exit the program when the window is closed
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//Window size / initial position
		frame.setSize(w, h);
		frame.setLocationRelativeTo(null);
		// setBounds(x, y, w, h);
		//Create an instance of PaintCanvas
		PaintCanvas canvas = new PaintCanvas();
		//Add to frame
		JPanel pane = new JPanel();
		frame.getContentPane().add(pane, BorderLayout.CENTER);
		JPanel paneB = new JPanel();
		frame.getContentPane().add(paneB, BorderLayout.NORTH);
		canvas.setPreferredSize(new Dimension(w, h));
		pane.add(canvas);
		/*Additional features*/
		//Erase all
		JButton clear = new JButton("CLEAR");
		clear.addActionListener(new ClearListener(canvas));
		paneB.add(clear);
		//Adjusting the line thickness
		JSlider slider = new JSlider(1, 50, 1); //Minimum value, maximum value, initial value
		slider.addChangeListener(new SliderListener(canvas)); //For interrupt processing
		paneB.add(slider);
		//Line color change
		String[] combodata = { "BLACK", "RED", "BLUE", "GREEN" };
		JComboBox combo = new JComboBox(combodata);
		combo.addActionListener(new ComboListener(canvas));
		paneB.add(combo);
		//Show window
		frame.setVisible(true);
	}
	//Canvas class
	static class PaintCanvas extends Canvas implements MouseListener,
			MouseMotionListener {
		//BufferedImage that holds the drawing contents
		private BufferedImage cImage = null;
		//Instance for drawing to cImage
		private Graphics2D g2d;
		//Line start and end coordinates
		private int x, y, xx, yy;
		//Drawing mode OR eraser mode
		private int type;
		//Line thickness
		public int width = 1;
		//Line color
		public Color c = Color.black;
		public PaintCanvas() {
			//Initialize coordinates
			x = -1;
			y = -1;
			xx = -1;
			yy = -1;
			type = 0;
			//Set MouseListener / MouseMotionListener
			addMouseListener(this);
			addMouseMotionListener(this);
			//Set canvas background to white
			setBackground(Color.white);
			//Generate a BufferedImage that holds the drawing contents
			cImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
			g2d = (Graphics2D) cImage.getGraphics();
			//Make the background of BufferedImage white
			g2d.setColor(Color.WHITE);
			g2d.fillRect(0, 0, w, h);
			//drawing
			repaint();
		}
		//Clear the canvas
		public void clear() {
			g2d.setColor(Color.WHITE);
			g2d.fillRect(0, 0, w, h);
			repaint();
		}
		//Change line thickness
		public void setStroke(int n) {
			width = n;
		}
		//Line color change
		public void setColorCombo(String color) {
			if (color.equals("BLACK")) {
				c = Color.black;
			} else if (color.equals("RED")) {
				c = Color.red;
			} else if (color.equals("BLUE")) {
				c = Color.blue;
			} else if (color.equals("GREEN")) {
				c = Color.green;
			}
		}
		public void paint(Graphics g) {
			//Drawing mode (drawing a line segment)
			if (type == 1) {
				if (x >= 0 && y >= 0 && xx >= 0 && yy >= 0) {
					BasicStroke stroke = new BasicStroke(width,
							BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
					g2d.setStroke(stroke);
					g2d.setColor(c);
					g2d.drawLine(xx, yy, x, y);
				}
				//Eraser mode
			} else if (type == 2) {
				if (x >= 0 && y >= 0 && xx >= 0 && yy >= 0) {
					//Set to a line segment with rounded ends
					BasicStroke stroke = new BasicStroke(50.0f,
							BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
					g2d.setStroke(stroke);
					g2d.setColor(Color.white);
					g2d.drawLine(xx, yy, x, y);
				}
			}
			//Reflect the drawing contents on the canvas
			g.drawImage(cImage, 0, 0, null);
		}
		@Override
		public void mouseDragged(MouseEvent e) {
			//Detects the button being pressed
			if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) {
				//Left button click (drawing mode)
				type = 1;
			}
			if ((e.getModifiers() & MouseEvent.BUTTON2_MASK) != 0) {
				//Middle button click
			}
			if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
				//Right button click (eraser mode)
				type = 2;
			}
			//Set past coordinates as start coordinates
			xx = x;
			yy = y;
			//Set new coordinates as end coordinates
			Point point = e.getPoint();
			x = point.x;
			y = point.y;
			//redraw
			repaint();
		}
		@Override
		public void mouseMoved(MouseEvent e) {
			//Initialize coordinates when dragging is complete
			x = -1;
			y = -1;
			xx = -1;
			yy = -1;
			type = 0;
		}
		@Override
		public void mouseClicked(MouseEvent e) {
		}
		@Override
		public void mousePressed(MouseEvent e) {
			Point point = e.getPoint();
			x = point.x;
			y = point.y;
		}
		@Override
		public void mouseReleased(MouseEvent e) {
		}
		@Override
		public void mouseEntered(MouseEvent e) {
		}
		@Override
		public void mouseExited(MouseEvent e) {
		}
	}
	//For clear button
	static class ClearListener implements ActionListener {
		PaintCanvas canvas;
		public ClearListener(PaintCanvas canvas) {
			super();
			this.canvas = canvas;
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			canvas.clear();
		}
	}
	//For slider
	static class SliderListener implements ChangeListener {
		PaintCanvas canvas;
		public SliderListener(PaintCanvas canvas) {
			super();
			this.canvas = canvas;
		}
		@Override
		public void stateChanged(ChangeEvent e) {
			JSlider source = (JSlider) e.getSource();
			int fps = (int) source.getValue();
			canvas.setStroke(fps);
		}
	}
	//For combo box
	static class ComboListener implements ActionListener {
		PaintCanvas canvas;
		public ComboListener(PaintCanvas canvas) {
			super();
			this.canvas = canvas;
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			JComboBox source = (JComboBox) e.getSource();
			String color = (String) source.getSelectedItem();
			canvas.setColorCombo(color);
		}
	}
}
Thank you for reading to the end!
Recommended Posts