How to use and apply Java's JFrame / Canvas class

Introduction

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:

Things to make this time

I would like to make a simple drawing application using the Jframe / Canvas class. The finished product will look like an image. : art: Screenshot 2018-11-27 at 10.06.48.png

Step1: Prepare JFrame

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: Screenshot 2018-11-27 at 09.49.39.png

Step2: Prepare Canvas

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. Screenshot 2018-11-27 at 09.50.11.png Let's be able to draw a picture here.

Step3: Detect mouse operation

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: Screenshot 2018-11-27 at 09.51.09.png

Step4: Draw a picture with the mouse

… 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! Screenshot 2018-11-27 at 09.52.19.png

Complete!

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: Screenshot 2018-11-27 at 10.06.48.png 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);
		}

	}

}

# at the end Since I posted to such a place for the first time this time, I think that there are many parts that can not be reached, We hope that it will be of some help to you.

Thank you for reading to the end!

Recommended Posts

How to use and apply Java's JFrame / Canvas class
[Java] How to use FileReader class and BufferedReader class
[Java] How to use Calendar class and Date class
How to use java class
How to use StringBurrer and Arrays.toString.
How to use EventBus3 and ThreadMode
How to use the wrapper class
How to use setDefaultCloseOperation () of JFrame
[Java] How to use LinkedHashMap class
[Java] How to use Math class
How to use OrientJS and OrientDB together
[Java] How to use the File class
[Java] How to use the HashMap class
How to use Java Scanner class (Note)
How to use substring and substr methods
[Java] How to use the Calendar class
How to use @Builder and @NoArgsConstructor together
[Ruby] How to use gsub method and sub method
How to use Segmented Control and points to note
How to use scope and pass processing (Jakarta)
How to use rbenv
How to use letter_opener_web
How to use with_option
How to use java.util.logging
How to use map
How to use Twitter4J
How to use active_hash! !!
How to use hidden_field_tag
[How to use label]
How to use identity
How to use hashes
How to use JUnit 5
How to use Dozer.mapper
How to use Gradle
How to use org.immutables
How to use java.util.stream.Collector
How to use VisualVM
How to use Map
[Java] How to use compareTo method of Date class
How to use RealSense with ubuntu 20.04 and ROS Noetic
How to create and execute method, Proc, Method class objects
[Java] How to use Map
How to use Chain API
[Java] How to use Map
How to use Priority Queuing
[Rails] How to use enum
How to use java Optional
How to use JUnit (beginner)
How to use Ruby return
[Rails] How to use enum
How to use @Builder (Lombok)
[Swift] How to use UserDefaults
How to use Swift UIScrollView
How to use Big Decimal
[Java] How to use Optional ②
[Java] How to use removeAll ()
How to use String [] args
[Java] How to use string.format
How to use rails join
How to use Java Map
Ruby: How to use cookies