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