I want to draw circle only after mouse gets click. As paintComponent method called itself, so first circle draw without click.
public class DrawPanel extends JPanel implements MouseListener {
private static final long serialVersionUID = 1L;
int x, y;
public DrawPanel() {
setBackground(Color.WHITE);
addMouseListener(this);
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fillOval(x, y, 20, 20);
}
#Override
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
}
There are a few issues with your code:
You never call super.paintComponent();
You only have one x and y
Note how when you resize the frame, some circles will disappear and it overall behaves in a strange way.
I would store all the Points where the user has clicked in an ArrayList and then loop through that list inside the paintComponent method. This way you can call super.paintComponent(); without the circles disappearing.
Changed, working code:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<Point> points;
public DrawPanel() {
points = new ArrayList<Point>();
setBackground(Color.WHITE);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
points.add(new Point(e.getX(), e.getY()));
repaint();
}
});
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.red);
for (Point point : points) {
g2.fillOval(point.x, point.y, 20, 20);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new DrawPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
});
}
}
You should place your circle inside its own class. That class will hold information on its location, radius, and its color. You can abstract your shape and have a list of shapes to draw on the panel. This will make it easy to implement a triangle, square, hexagon, etc. later.
You can add more methods and attributes to your shape objects later and only have to change their internal implementation of THEIR OWN paintComponent(g) method. This makes the DrawPanel depend on how each Shape does its own drawing.
App.java
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class App {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("Circle Click Application");
DrawPanel p = new DrawPanel(10f);
p.setPreferredSize(new Dimension(300, 200));;
f.setContentPane(p);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
DrawPanel.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
public class DrawPanel extends JPanel implements MouseListener {
private static final long serialVersionUID = -6817035652787391530L;
private List<Shape> shapes;
protected float radius;
private float sat = 0.7f;
private float bri = 0.8f;
public DrawPanel(float radius) {
this.shapes = new ArrayList<Shape>();
this.radius = radius;
setBackground(Color.WHITE);
addMouseListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Shape shape : shapes) {
shape.paintComponent(g);
}
}
#Override
public void mouseClicked(MouseEvent e) {
shapes.add(new Circle(e.getX(), e.getY(), radius, ColorUtils.randHue(sat, bri)));
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
Shape.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public interface Shape {
Point getOrigin();
void setOrigin(Point origin);
Color getColor();
void setColor(Color color);
void paintComponent(Graphics g);
}
Circle.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public class Circle implements Shape {
private Point origin;
private float radius;
private Color color;
public Circle() {
this(0, 0, 0.5f, Color.BLACK);
}
public Circle(int x, int y, float radius, Color color) {
this(new Point(x, y), radius, color);
}
public Circle(Point origin, float radius, Color color) {
this.origin = origin;
this.radius = radius;
this.color = color;
}
#Override
public Point getOrigin() {
return origin;
}
#Override
public void setOrigin(Point origin) {
this.origin = origin;
}
public float getRadius() {
return radius;
}
public void setRadius(float radius) {
this.radius = radius;
}
#Override
public Color getColor() {
return color;
}
#Override
public void setColor(Color color) {
this.color = color;
}
#Override
public void paintComponent(Graphics g) {
int diameter = (int) (this.radius * 2);
int x = (int) (origin.x - this.radius);
int y = (int) (origin.y - this.radius);
g.setColor(this.color);
g.fillOval(x, y, diameter, diameter);
}
}
ColorUtils.java
import java.awt.Color;
import java.util.Random;
public class ColorUtils {
private static final Random RAND;
static {
RAND = new Random(System.currentTimeMillis());
}
public static Color randHue(float saturation, float brightness) {
return Color.getHSBColor(RAND.nextFloat(), saturation, brightness);
}
}
Extension
You can easily add a class such as a Triangle just by implementing the Shape interface.
DrawPanel#mouseClicked
#Override
public void mouseClicked(MouseEvent e) {
long time = System.currentTimeMillis();
boolean isEven = time % 2 == 0;
if (isEven) {
shapes.add(new Circle(e.getX(), e.getY(), radius, ColorUtils.randHue(sat, bri)));
} else {
shapes.add(new Triangle(e.getX(), e.getY(), radius * 2, ColorUtils.randHue(sat, bri)));
}
repaint();
}
Triangle.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.geom.Point2D;
public class Triangle implements Shape {
private Point origin;
private float side;
private Color color;
private Polygon poly;
public Triangle(int x, int y, float side, Color color) {
this(new Point(x, y), side, color);
}
public Triangle(Point origin, float side, Color color) {
this.origin = origin;
this.side = side;
this.color = color;
recalculate();
}
protected void recalculate() {
this.poly = createPolygon((float) origin.getX(), (float) origin.getY(), side, false);
}
protected Polygon createPolygon(float x, float y, float side, boolean invert) {
float xOff = side / 2f;
float yOff = (float) (xOff * Math.sqrt(3));
float r1 = 1f / 3f;
float r2 = 2f / 3f;
if (invert) {
yOff *= -1;
}
return createPolygon(new Point2D.Float[] {
new Point2D.Float(x, y - (yOff * r2)), // Top
new Point2D.Float(x - xOff, y + (yOff * r1)), // Left
new Point2D.Float(x + xOff, y + (yOff * r1)) // Right
});
}
protected Polygon createPolygon(Point2D.Float[] points) {
int nPoints = points.length + 1;
int xCoords[] = new int[nPoints];
int yCoords[] = new int[nPoints];
for (int i = 0; i < nPoints; i++) {
xCoords[i] = (int) points[i % points.length].x;
yCoords[i] = (int) points[i % points.length].y;
}
return new Polygon(xCoords, yCoords, nPoints);
}
#Override
public Point getOrigin() {
return origin;
}
#Override
public void setOrigin(Point origin) {
this.origin = origin;
recalculate();
}
public float getSide() {
return side;
}
public void setSide(float side) {
this.side = side;
recalculate();
}
#Override
public Color getColor() {
return color;
}
#Override
public void setColor(Color color) {
this.color = color;
}
#Override
public void paintComponent(Graphics g) {
g.setColor(this.color);
g.fillPolygon(poly);
}
}
You should have some initial state, so you know not to draw when it is set.
This can be done with an easy boolean variable, that you set to true when the user has pressed on the screen.
public class DrawPanel extends JPanel implements MouseListener {
private static final long serialVersionUID = 1L;
int x, y;
boolean mustDraw = false;
public DrawPanel() {
setBackground(Color.WHITE);
addMouseListener(this);
}
public void paintComponent(Graphics g) {
if(!mustDraw) return;
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fillOval(x, y, 20, 20);
}
#Override
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
mustDraw = true;
repaint();
}
}
Related
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.border.BevelBorder;
public class Cliente extends JPanel {
private JButton adelanteButton;
private JButton undoButton;
private JPanel panel1;
private JPanel panelDibujo;
private Rectangulo rectangulo = new Rectangulo();
Originator originator;
Caretaker caretaker;
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Patron Memento");
Cliente cliente = new Cliente();
frame.setContentPane(cliente.panel1);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Memento m : caretaker.history) {
System.out.println("forcitooooooo");
dibujar(m.getState(), Color.GREEN);
}
}
public Cliente() {
caretaker = new Caretaker();
originator = new Originator();
createUIComponents();
undoButton.addActionListener(e -> {
caretaker.anterior();
panelDibujo.repaint();
});
panelDibujo.setBackground(Color.WHITE);
panelDibujo.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
panelDibujo.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
MousePressedEvent(e);
}
#Override
public void mouseReleased(MouseEvent e) {
MouseReleasedEvent(e);
}
});
}
private void createUIComponents() {
}
private void MousePressedEvent(MouseEvent e){
rectangulo.setX1(e.getX());
rectangulo.setY1(e.getY());
}
private void MouseReleasedEvent(MouseEvent e){
rectangulo.setX2(e.getX());
rectangulo.setY2(e.getY());
originator.setState(rectangulo);
dibujar(rectangulo, Color.orange);
caretaker.addMemento(originator.CreateMemento());
rectangulo = new Rectangulo();
}
public void dibujar(Rectangulo r, Color c) {
Graphics g = panelDibujo.getGraphics();
g.setColor(c);
g.drawRect(r.getX1(), r.getY1(), r.getX2() - r.getX1(), r.getY2() - r.getY1());
g.dispose();
}
}
Hello i am applying the memento pattern by using a jpanel and drawing some rectangles inside, right now my code is working fine about drawing with the mouse events, but the issue is when i try to undo. My logic so far is clear the jpanel and redo all the rectangles minus the last one.
But after clearing my jpanel is not drawing again :( can someone help me to fix it? thank you
Caretaker.java
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Stack;
public class Caretaker {
LinkedList<Memento> history;
int indice;
public Caretaker(){
history = new LinkedList<>();
indice = 0;
}
void addMemento(Memento m){
if (history.size() == indice || history.isEmpty()){
indice++;
history.add(m);
}else {
indice = history.size()-1;
history.subList(indice +1, history.size()).clear();
}
}
Memento anterior(){
if (history.size() > 0){
indice--;
return history.removeLast();
}
JOptionPane.showMessageDialog(null, "No hay mas wey!");
return null;
}
Memento siguiente(){
if (indice < history.size()+1){
indice++;
return history.get(indice+1);
}
JOptionPane.showMessageDialog(null, "No hay mas wey!");
return null;
}
public void redibujar(JPanel f){
Graphics g = f.getGraphics();
for (Memento m: history) {
g.drawRect(m.getState().getX1(), m.getState().getY1(), m.getState().getX2() - m.getState().getX1(), m.getState().getY2() - m.getState().getY1());
g.dispose();
}
}
public void clear(){
history.clear();
indice = 0;
}
}
Memento.java
public class Memento {
Rectangulo state;
/*
Constructor, unica manera de mandar/crear/guardar los datos
*/
public Memento(Rectangulo state) {
this.state = state;
}
public Memento(){
state = new Rectangulo();
}
Rectangulo getState(){
return state;
}
}
Originator.java
public class Originator {
Rectangulo state;
public void setState(Rectangulo rectangulo){
this.state = rectangulo;
}
public Memento CreateMemento(){
return new Memento(state);
}
public void setMemento(Memento m) {
setState(m.getState());
}
}
Rectangulo.java
import java.awt.*;
public class Rectangulo {
private int x1;
private int x2;
private int y1;
private int y2;
Rectangulo(){
}
public Rectangulo(int x1, int x2, int y1, int y2) {
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
}
public int getX1() {
return x1;
}
public void setX1(int x1) {
this.x1 = x1;
}
public int getX2() {
return x2;
}
public void setX2(int x2) {
this.x2 = x2;
}
public int getY1() {
return y1;
}
public void setY1(int y1) {
this.y1 = y1;
}
public int getY2() {
return y2;
}
public void setY2(int y2) {
this.y2 = y2;
}
public void draw(Graphics g){
g.setColor(Color.orange);
g.drawRect(this.getX1(), this.getY1(), this.getX2() - this.getX1(), this.getY2() - this.getY1());
}
}
Again, you're not drawing correctly. You are trying to render using a JPanel, cliente, that is never added to the GUI, and you're trying to use a Graphics object that is extracted from this unrendered component, making the Graphics object thus obtained short-lived and unstable.
Instead, do all drawing in the paintComponent method. You can use a BufferedImage and draw that in paintComponent if desired, especially if you want images with objects that show different colors, or you can use your List (here a LinkedList, but ArrayList will work) and draw in paintComponent. For instance, something simple like:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class Cliente2 extends JPanel {
private static final int BI_WIDTH = 800;
private static final int BI_HEIGHT = 650;
private Rectangle drawingRect = null;
// private java.util.List<Rectangulo> rectangulos = new ArrayList<>();
List<Rectangulo2> rectangulos = new ArrayList<>();
private JButton clearBtn = new JButton("Clear");
public Cliente2() {
setBackground(Color.WHITE);
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
clearBtn.addActionListener(e -> clear());
add(clearBtn);
}
private void clear() {
rectangulos.clear();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(BI_WIDTH, BI_HEIGHT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (drawingRect != null) {
g2.setColor(Color.LIGHT_GRAY);
g2.draw(drawingRect);
}
for (Rectangulo2 rectangulo : rectangulos) {
rectangulo.draw(g2);
}
}
private class MyMouse extends MouseAdapter {
private Point p0;
#Override
public void mousePressed(MouseEvent e) {
p0 = e.getPoint();
}
#Override
public void mouseDragged(MouseEvent e) {
drawingRect = createDrawingRect(e);
repaint();
}
private Rectangle createDrawingRect(MouseEvent e) {
Point p1 = e.getPoint();
int x = Math.min(p0.x, p1.x);
int y = Math.min(p0.y, p1.y);
int width = Math.abs(p0.x - p1.x);
int height = Math.abs(p0.y - p1.y);
return new Rectangle(x, y, width, height);
}
#Override
public void mouseReleased(MouseEvent e) {
// lets create some random colors:
float hue = (float) Math.random();
float brightness = (float) Math.random();
Color color = Color.getHSBColor(hue, 1f, brightness);
Rectangulo2 rectangulo = new Rectangulo2(color, p0, e.getPoint());
rectangulos.add(rectangulo);
drawingRect = null;
repaint();
}
}
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Patron Memento");
// Cliente cliente = new Cliente();
// frame.setContentPane(cliente.panel1);
frame.add(new Cliente2());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
class Rectangulo2 {
private static final Stroke STROKE = new BasicStroke(3f);
private Color color;
private Point p0, p1;
public Rectangulo2() {
}
public Rectangulo2(Color color, Point p0, Point p1) {
super();
this.color = color;
this.p0 = p0;
this.p1 = p1;
}
public Color getColor() {
return color;
}
public Point getP0() {
return p0;
}
public Point getP1() {
return p1;
}
public void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(color);
int x = Math.min(p0.x, p1.x);
int y = Math.min(p0.y, p1.y);
int width = Math.abs(p0.x - p1.x);
int height = Math.abs(p0.y - p1.y);
g2.fillRect(x, y, width, height);
g2.setStroke(STROKE);
g2.setColor(Color.BLACK);
g2.drawRect(x, y, width, height);
g2.dispose();
}
}
I'm trying to draw boundaries for a character that I'm moving around on a JFrame. I know how to draw rectangles to establish boundaries, but how could I do this if the area that I want to draw bounds for isn't a rectangle?
Say for example I want to move the green circle around in the square, but the blue diamond represents the boundaries, and the circle cannot go past those bounds. How could I do this?
This is the kind of thing I use for this is line/point collision:
http://www.jeffreythompson.org/collision-detection/line-circle.php
it's pretty mathy but it works nicely and isn't buggy
Just treat your circle as a rectangle and validate if the circle is inside your diamond with the contains method of Rectangle (See docs). Small snipped:
private Rectangle rect = new Rectangle(25, 25, 450, 450);
private Rectangle circle = new Rectangle(250, 250, 50, 50);
if(rect.contains(tmp)) {
// True, if the circle does not touch any square-line
}
A full example of the code:
package circlemoving;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.*;
import javax.swing.*;
public class CircleMoving {
public static void main(String[] args) {
MainPanel mp = new MainPanel();
JFrame jFrame = new JFrame();
jFrame.add(mp);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
jFrame.pack();
jFrame.addKeyListener(new KeyListener() {
#Override public void keyTyped(KeyEvent e) {}
#Override public void keyReleased(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {
mp.update(e.getKeyCode());
}
});
}
private static class MainPanel extends JPanel {
private Rectangle rect = new Rectangle(25, 25, 450, 450);
private Rectangle circle = new Rectangle(250, 250, 50, 50);
public MainPanel() {
setPreferredSize(new Dimension(500, 500));
repaint();
}
#Override
public void paintComponent(Graphics grahpics) {
super.paintComponent(grahpics);
Graphics2D g2d = (Graphics2D) grahpics;
g2d.setStroke(new BasicStroke(1));
g2d.setColor(Color.BLUE);
g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
g2d.setStroke(new BasicStroke(1));
g2d.setColor(Color.RED);
g2d.drawOval(circle.x, circle.y, circle.width, circle.width);
}
public void update(int keyCode) {
int tmpX = circle.x;
int tmpY = circle.y;
switch (keyCode) {
case 39:
tmpX = circle.x + 3;
break;
case 37:
tmpX = circle.x - 3;
break;
case 38:
tmpY = circle.y - 3;
break;
case 40:
tmpY = circle.y + 3;
break;
default:
break;
}
Rectangle tmp = new Rectangle(tmpX, tmpY, circle.width, circle.height);
if(rect.contains(tmp)) {
circle.x = tmpX;
circle.y = tmpY;
repaint();
}
}
}
}
Result:
I created a simple GUI to demonstrate how to use a polygon boundary in a Swing GUI. Here's the GUI.
You can't see in the picture, but you can grab the green circle (the player) with the mouse and drag it anywhere inside the blue diamond (the boundary). The code will not let you drag the player outside the boundary.
Here's what I did.
I created two model classes. One for the boundary, and one for the player. I used this logical model to draw in the view and do calculations in the mouse listener. This is an application of the model / view / controller pattern.
I created a simple Swing GUI with a drawing panel. I calculated where the start of the oval would be so I could keep the center point and radius in the model.
I created a mouse listener class to listen for the mouse press and mouse release.
And here's the code. Hopefully, there's not much to explain. The Polygon class has a method, contains, that checks if a rectangle is completely inside the polygon. I converted the circle to a rectangle in the listener so I could use this method.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Rectangle2D;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
public class PolygonBoundary implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new PolygonBoundary());
}
private Boundary boundary;
private Dimension dpSize;
private Player player;
public PolygonBoundary() {
this.dpSize = new Dimension(400, 400);
Polygon polygon = new Polygon();
polygon.addPoint(200, 0);
polygon.addPoint(0, 200);
polygon.addPoint(200, 400);
polygon.addPoint(400, 200);
this.boundary = new Boundary(polygon, Color.BLUE);
this.player = new Player(200, 200, 24, Color.GREEN);
}
#Override
public void run() {
JFrame frame = new JFrame("Polygon Boundary");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawingPanel drawingPanel =
new DrawingPanel(dpSize, boundary, player);
frame.add(drawingPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private Boundary boundary;
private Player player;
public DrawingPanel(Dimension size, Boundary boundary,
Player player) {
this.boundary = boundary;
this.player = player;
this.setPreferredSize(size);
Border border = BorderFactory.createLineBorder(
Color.BLACK, 4);
this.setBorder(border);
PlayerMotion playerMotion =
new PlayerMotion(this, boundary, player);
this.addMouseListener(playerMotion);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(boundary.getColor());
g2d.setStroke(new BasicStroke(4f));
g2d.drawPolygon(boundary.getPolygon());
g2d.setColor(player.getColor());
Point center = player.getCenter();
int radius = player.getRadius();
int diameter = radius + radius;
g2d.drawOval(center.x - radius, center.y - radius,
diameter, diameter);
}
}
public class PlayerMotion implements MouseListener {
private Boundary boundary;
private JPanel panel;
private Player player;
private Point originalPoint;
public PlayerMotion(JPanel panel, Boundary boundary,
Player player) {
this.panel = panel;
this.boundary = boundary;
this.player = player;
}
#Override
public void mouseClicked(MouseEvent event) {
}
#Override
public void mousePressed(MouseEvent event) {
Point center = player.getCenter();
int radius = player.getRadius();
Rectangle2D r2d = createRectangle(center, radius);
if (r2d.contains(event.getPoint())) {
originalPoint = event.getPoint();
}
}
#Override
public void mouseReleased(MouseEvent event) {
if (originalPoint == null) {
return;
}
Point endPoint = event.getPoint();
Point center = player.getCenter();
int radius = player.getRadius();
int newX = center.x - originalPoint.x + endPoint.x;
int newY = center.y - originalPoint.y + endPoint.y;
Point newPoint = new Point(newX, newY);
Rectangle2D r2d = createRectangle(newPoint, radius);
Polygon polygon = boundary.getPolygon();
if (polygon.contains(r2d)) {
player.setCenter(newPoint);
panel.repaint();
}
originalPoint = null;
}
private Rectangle2D createRectangle(Point center, int radius) {
double dx = center.x - radius;
double dy = center.y - radius;
double d = radius + radius;
Rectangle2D r2d = new Rectangle2D.Double(dx, dy, d, d);
return r2d;
}
#Override
public void mouseEntered(MouseEvent event) {
}
#Override
public void mouseExited(MouseEvent event) {
}
}
public class Boundary {
private final Color color;
private final Polygon polygon;
public Boundary(Polygon polygon, Color color) {
this.polygon = polygon;
this.color = color;
}
public Polygon getPolygon() {
return polygon;
}
public Color getColor() {
return color;
}
}
public class Player {
private final int radius;
private final Color color;
private Point center;
public Player(int x, int y, int radius, Color color) {
this.center = new Point(x, y);
this.radius = radius;
this.color = color;
}
public int getRadius() {
return radius;
}
public Point getCenter() {
return center;
}
public void setCenter(Point center) {
this.center = center;
}
public Color getColor() {
return color;
}
}
}
I want to drag one object at a time but this code drags both the objects at a time
package javaPgm;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
import javax.swing.ImageIcon;
import java.awt.Color;
import java.awt.Graphics.*;
public class Drag extends Applet
implements MouseListener, MouseMotionListener {
int width, height;
int x, y; // coordinates of upper left corner of the box
int mx, my; // the most recently recorded mouse coordinates
boolean isMouseDraggingBox = false;
public void init() {
width = getSize().width;
height = getSize().height;
x = width/2 - 20;
y = height/2 - 20;
addMouseListener( this );
addMouseMotionListener( this );
}
public void mouseEntered( MouseEvent e ) { }
public void mouseExited( MouseEvent e ) { }
public void mouseClicked( MouseEvent e ) { }
public void mousePressed( MouseEvent e ) {
mx = e.getX();
my = e.getY();
if ( x < mx && mx < x+40 && y < my && my < y+40 ) {
isMouseDraggingBox = true;
}
e.consume();// consumes the current event
}
public void mouseReleased( MouseEvent e ) {
isMouseDraggingBox = false;
e.consume();
}
public void mouseMoved( MouseEvent e ) { }
public void mouseDragged( MouseEvent e ) {
if ( isMouseDraggingBox ) {
int new_mx = e.getX();
int new_my = e.getY();
x += new_mx - mx;
y += new_my - my;
mx = new_mx;
my = new_my;
repaint();
e.consume();
}
}
public void paint( Graphics g ) {
g.drawRect( 20, 40, 50, 85 );
g.drawString("circle",20 , 38);
Font f = new Font("TimesRoman", Font.PLAIN, 20);// to set font style and size
g.setFont(f);
g.drawString("RED=Positive charge", 175, 188);// to write a text
g.drawString("BLUE=negative charge", 199, 210);
g.drawRect(100,140,60,85);
g.setColor(Color.red);
g.fillOval(x,y,15,15);
g.setColor(Color.blue);
g.fillOval(x-110,y-135,15,15);
setBackground(Color.yellow);
for(int i=0;i<=950;i+=30){// to draw horizontal and vertical lines
g.setColor(Color.orange);
g.drawLine(i,0,i,950);
}
for(int j=0;j<=950;j+=30){
g.drawLine(0, j, 950, j);
}
}
}
The first thing you need is some way to tell the difference between your "objects".
The next thing you need is some way to reference this objects in a convenient method. You could use an array, but I'm lazy and prefer to use a List
Once you have these two things, painting the boxes is just a matter of looping through the List and determining which object was clicked is becomes basically the same process...
To that end, I wrapped a java.awt.Rectangle around a custom Box class, which also maintains color information, this makes it much easier to manage as Rectangle has some very useful methods and can be painted easily.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JApplet;
import javax.swing.JPanel;
public class WhatADag extends JApplet {
#Override
public void init() {
add(new DragPane());
}
public class DragPane extends JPanel {
private List<Box> boxes;
public DragPane() {
boxes = new ArrayList<>(25);
boxes.add(new Box(0, 0, 50, 50, Color.RED));
boxes.add(new Box(150, 150, 50, 50, Color.BLUE));
MouseAdapter handler = new MouseAdapter() {
private Box hitBox;
private Point offset;
#Override
public void mousePressed(MouseEvent e) {
Point mp = e.getPoint();
for (Box box : boxes) {
if (box.getBounds().contains(mp)) {
hitBox = box;
offset = new Point();
offset.x = mp.x - box.getBounds().x;
offset.y = mp.y - box.getBounds().y;
}
}
}
#Override
public void mouseReleased(MouseEvent e) {
hitBox = null;
}
#Override
public void mouseDragged(MouseEvent e) {
if (hitBox != null) {
Point mp = e.getPoint();
Rectangle bounds = hitBox.getBounds();
bounds.x = mp.x - offset.x;
bounds.y = mp.y - offset.y;
repaint();
}
}
};
addMouseListener(handler);
addMouseMotionListener(handler);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Box rect : boxes) {
g2d.setColor(rect.getColor());
g2d.fill(rect.getBounds());
}
g2d.dispose();
}
}
public class Box {
private Color color;
private Rectangle rectangle;
public Box(int x, int y, int width, int height, Color color) {
rectangle = new Rectangle(x, y, width, height);
setColor(color);
}
public void setColor(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
public Rectangle getBounds() {
return rectangle;
}
}
}
Take a look at Performing Custom Painting and 2D Graphics for more details
My program involves drawing triangles where i click them.
There are two classes, Ecad and Line class. Ecad is the main frame and Line class is for drawing lines.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Ecad extends JFrame implements MouseListener{
ArrayList<Line2> lines=new ArrayList();
public Ecad(){
this.setVisible(true);
this.setSize(600,400);
this.addMouseListener(this);
}
public void mouseReleased(MouseEvent me){
Point p1,p2,p3;
int X=me.getX();
int Y=me.getY();
p1=new Point(X,Y);
p2=new Point((int)(p1.getX()-100),(int)(p1.getY()+(1.732/2*200)));
p3=new Point((int)(p1.getX()+100),(int)(p1.getY()+(1.732/2*200)));
Line2 l1=new Line2(p2,p1);
Line2 l2=new Line2(p1,p3);
Line2 l3=new Line2(p2,p3);
lines.add(l1);
lines.add(l2);
lines.add(l3);
this.repaint();
}
public void mouseClicked(MouseEvent me){
}
public void mouseExited(MouseEvent me){
}
public void mouseEntered(MouseEvent me){
}
public void mousePressed(MouseEvent me){
}
public void mouseMoved(MouseEvent me){
}
public static void main(String args[]){
new Ecad();
}
public void paint(Graphics g){
Graphics2D g2=(Graphics2D)g;
super.paintComponents(g2);
//g2.scale(0.5, 0.5);
for(final Line2 r:lines){
r.paint((Graphics2D)g2);
}
}
}
This is the Line class
import java.awt.*;
public class Line2 {
Point start,end;
public Line2(Point a,Point b){
start=a;
end=b;
}
public void paint(Graphics2D g){
g.drawLine((int)start.getX(),(int)start.getY(),(int)end.getX(),(int)end.getY());
}
}
In the Ecad class's paint() method, if i use the scale option to zoom in or out, the mouse co-ordinates does not get transformed. So after it is zoomed, if i click at one point, the triangle gets placed at some other point. Is there a way to transform the mouse co-ordinates as well when i scale the Graphics component??
Again, you should translate your shape that you're drawing using the scale and a fixed point (again here it appears that the fixed point of each shape would be the apex of the triangle, but it could be the center should you so decide. The translation is based on simple geometric principles and would be the fixedPoint.x * (1 - scale) / scale, and the same for the y translation.
For example (and this one uses a JPanel as your example above should):
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.List;
class EcadB extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
private List<MyShape> myShapes = new ArrayList<MyShape>();
private double scale = 1.0;
private JSlider slider = new JSlider(0, 200, 100);
public EcadB() {
addMouseListener(new MyMouseAdapter());
setLayout(new BorderLayout());
slider.setOpaque(false);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(10);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.addChangeListener(new SliderChangeListener());
add(slider, BorderLayout.SOUTH);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Graphics2D g2b = (Graphics2D)g2.create();
g2b.scale(scale, scale);
for (MyShape myShape : myShapes) {
myShape.draw(g2b, scale);
}
g2b.dispose();
}
public void setScale(double scale) {
this.scale = scale;
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
Point2D p1 = e.getPoint();
Point2D p2 = new Point((int) (p1.getX() - 100),
(int) (p1.getY() + (1.732 / 2 * 200)));
Point2D p3 = new Point((int) (p1.getX() + 100),
(int) (p1.getY() + (1.732 / 2 * 200)));
Path2D path = new Path2D.Double();
path.moveTo(p1.getX(), p1.getY());
path.lineTo(p2.getX(), p2.getY());
path.lineTo(p3.getX(), p3.getY());
path.lineTo(p1.getX(), p1.getY());
myShapes.add(new MyShape(path, p1));
repaint();
}
}
private class SliderChangeListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent arg0) {
double value = slider.getValue() / 100.0;
setScale(value);
}
}
public static void main(String args[]) {
// new Ecad();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
EcadB ecadB = new EcadB();
JFrame frame = new JFrame("Scale");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(ecadB);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
class MyShape {
Shape shape;
Point2D fixedPoint;
public MyShape(Shape shape, Point2D fixedPoint) {
this.shape = shape;
this.fixedPoint = fixedPoint;
}
public void draw(Graphics2D g2, double scale) {
Graphics2D g2b = (Graphics2D) g2.create();
double tx = fixedPoint.getX() * (1.0 - scale) / scale;
double ty = fixedPoint.getY() * (1.0 - scale) / scale;
g2b.translate(tx, ty);
g2b.draw(shape);
g2b.dispose();
}
}
Note that I make copies of my Graphics object before transforming them so as to not have the transform effect other objects that may be drawn by the Graphic object. For example if you get rid of the Graphics2D copy that I use in the JPanel's paintComponent(...) method, you'll find the JSlider gets scaled with everything else.
i have a program similar to paint. and that i am trying to implement a change pen color however when i change the color, everything currently drawn is changed to the color RED for example in my program,how can i make it such that it will not repaint everything currently drawn to the currently changed color?Below code will compile and run
Class for the JPanel drawing area
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
//refer to http://jkost.ergoway.gr/jnkjavaconnection/freedraw.html for the algorithm.
public class STDrawingArea extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
ArrayList<Rectangle> dPoint = new ArrayList<Rectangle>();
Point point = new Point(-1,-1);
private Color currentColor;
public STDrawingArea()
{
setBorder(BorderFactory.createLineBorder(Color.black));
setBackground(Color.WHITE);
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e)
{
dPoint.add(new Rectangle(point.x,point.y,e.getX(),e.getY()));
point.x = e.getX();
point.y = e.getY();
repaint();
}
});
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e)
{
System.out.println("mousePressed X: "+e.getX()+"mousePressed Y: "+e.getY());
dPoint.add(new Rectangle(e.getX(),e.getY(),-1,-1));
point.x = e.getX();
point.y = e.getY();
}
});
addMouseListener(new MouseAdapter(){
public void mouseReleased(MouseEvent e)
{
System.out.println("mouseReleased X: "+e.getX()+"mouseReleased Y: "+e.getY());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(700,500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(getCurrentColor());
for (int i=0; i < dPoint.size(); i++) {
Rectangle r = dPoint.get(i);
if (r.width != -1)
{
g.drawLine(r.x, r.y, r.width, r.height);
}
}
/* Draw current point.*/
g.drawLine(point.x, point.y, point.x, point.y);
}
//set current drawing color
public void changePenColor(Color color)
{
if (color == null)
setCurrentColor(Color.BLACK);
else
setCurrentColor(color);
}
//clear drawings method
public void clearDrawings()
{
if(!(dPoint==null))
{
dPoint.clear();
repaint();
}
}
private void setCurrentColor(Color currentColor) {
this.currentColor = currentColor;
}
private Color getCurrentColor() {
return currentColor;
}
}
Test main class.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class STTestMain extends JFrame {
STDrawingArea drawingArea = new STDrawingArea();
public STTestMain()
{
//JFrame settings
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Spelling Trainer");
setResizable(false);
setVisible(true);
//Panel of buttons
JPanel buttonContainer = new JPanel();
JButton btnPenColor = new JButton("Red Pen");
buttonContainer.add(btnPenColor);
//Drawing Area instantiation
//Adding things to JFrame
getContentPane().add(drawingArea);
getContentPane().add(buttonContainer,BorderLayout.PAGE_END);
pack();
//button listener
btnPenColor.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
drawingArea.changePenColor(Color.RED);
}
});
}
public static void main(String args[])
{
STTestMain test = new STTestMain();
}
}
One way:
Use your ArrayList to draw the current curve as it is being drawn, but
Use a BufferedImage to draw your completed curves
You would do this on mouseReleased and would draw the current curve to the BufferedImage using the current color.
You'll also need to re-initialize your ArrayList of points after drawing to the BufferedImage.
Don't forget to dispose of the BufferedImage's Graphics object after you're done using it.
Draw the BufferedImage in your paintComponent method after super.paintComponent but before drawing your current curve.
This way when you change the color of your drawing, only the current curve is effected.
EDIT
You've mentioned in a comment that you're not familiar with BufferedImage, and are looking for another way. I suppose you could create a class that holds an ArrayList of Points together with a Color, and then on each mouseReleased create an object of this class and add it to an ArrayList in your drawing panel. Then your paintComponent method could iterate through that ArrayList, drawing the list of Points with their associated color, but my gut tells me that you're an intelligent guy and that you'd pick up on how to use a BufferedImage in no time. I really think it's the best solution. And if you try it and it flops, show us your code, and we'll likely be able to help you.
EDIT 2
The BufferedImage constructor will need the image width, height and an image type -- something I'm not 100% familiar with. I usually use BufferedImage.TYPE_INT_RGB for general purpose drawing, and BufferedImage.TYPE_INT_ARGB for general purpose that needs an alpha too. Then you'll extract a Graphics object out of the BufferedImage, say getGraphics() if all you need is a Graphics object and not a Graphics2D object. Then when you initialize the BufferedImage in your constructor, fill it with a Color.white, just as you for your JPanel. Then dispose the Graphics object. Then each time you want to draw, you getGraphics, draw with it, just like you do in the paintComponent method, dispose of the Graphics when done, and finally draw the BufferedImage in the paintComponent via the drawImage method.
EDIT 3
Example program that doesn't do quite what you are trying to do but does illustrate use of a BufferedImage with drawing. This program changes the color each time a new path or curve is drawn.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.*;
public class STTestSimple {
private static void createAndShowUI() {
STDrawPanel drawPanel = new STDrawPanel();
STMouseAdapter mAdapter = new STMouseAdapter(drawPanel);
drawPanel.addMouseListener(mAdapter);
drawPanel.addMouseMotionListener(mAdapter);
JFrame frame = new JFrame("Drawing");
frame.getContentPane().add(drawPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
#SuppressWarnings("serial")
class STDrawPanel extends JPanel {
private static final int ST_WIDTH = 700;
private static final int ST_HEIGHT = 500;
private static final Color BACKGROUND_COLOR = Color.white;
private static final float STROKE_WIDTH = 6f;
private static final Stroke STROKE = new BasicStroke(STROKE_WIDTH,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
private static final Color[] colors = {Color.black, Color.blue, Color.red,
Color.green, Color.orange, Color.MAGENTA};
private BufferedImage bImage = new BufferedImage(ST_WIDTH, ST_HEIGHT,
BufferedImage.TYPE_INT_RGB);
private Color color = Color.black;
private ArrayList<Point> points = new ArrayList<Point>();
private int colorIndex = 0;
public STDrawPanel() {
Graphics g = bImage.getGraphics();
g.setColor(BACKGROUND_COLOR);
g.fillRect(0, 0, ST_WIDTH, ST_HEIGHT);
g.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bImage, 0, 0, null);
Graphics2D g2 = (Graphics2D) g;
drawCurve(g2);
}
private void addCurveToBufferedImage() {
Graphics2D g2 = bImage.createGraphics();
drawCurve(g2);
g2.dispose();
}
private void drawCurve(Graphics2D g2) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(STROKE);
g2.setColor(color);
if (points != null && points.size() > 1) {
for (int i = 0; i < points.size() - 1; i++) {
int x1 = points.get(i).x;
int y1 = points.get(i).y;
int x2 = points.get(i + 1).x;
int y2 = points.get(i + 1).y;
g2.drawLine(x1, y1, x2, y2);
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(ST_WIDTH, ST_HEIGHT);
}
public void curveStart(Point point) {
points.clear();
points.add(point);
}
public void curveEnd(Point point) {
points.add(point);
addCurveToBufferedImage();
points.clear();
repaint();
colorIndex++;
colorIndex %= colors.length;
setColor(colors[colorIndex]);
}
public void curveAdd(Point point) {
points.add(point);
repaint();
}
public void setColor(Color color) {
this.color = color;
}
}
class STMouseAdapter extends MouseAdapter {
private STDrawPanel drawPanel;
public STMouseAdapter(STDrawPanel drawPanel) {
this.drawPanel = drawPanel;
}
#Override
public void mousePressed(MouseEvent e) {
drawPanel.curveStart(e.getPoint());
}
#Override
public void mouseReleased(MouseEvent e) {
drawPanel.curveEnd(e.getPoint());
}
#Override
public void mouseDragged(MouseEvent e) {
drawPanel.curveAdd(e.getPoint());
}
}
Custom Painting Approaches gives two ideas on how you might do this.
Thanks hovercraft, i've done it looking at your code and fiddling around lol.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
public class STDrawingArea extends JPanel {
/**
*
*/
private static final int DA_WIDTH = 700;
private static final int DA_HEIGHT = 500;
private static final Color DA_BGCOLOR = Color.WHITE;
private static final long serialVersionUID = 1L;
ArrayList<Point> points = new ArrayList<Point>();
private Color currentColor;
BufferedImage bImage = new BufferedImage(DA_WIDTH, DA_HEIGHT, BufferedImage.TYPE_INT_RGB);
public STDrawingArea()
{
setBorder(BorderFactory.createLineBorder(Color.black));
//Basic Settings for bImage
Graphics g2d = bImage.getGraphics();
g2d.setColor(DA_BGCOLOR);
g2d.fillRect(0, 0, DA_WIDTH, DA_HEIGHT);
g2d.dispose();
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e)
{
points.clear();
points.add(e.getPoint());
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e)
{
points.add(e.getPoint());
repaint();
}
});
addMouseListener(new MouseAdapter(){
public void mouseReleased(MouseEvent e)
{
points.add(e.getPoint());
points.clear();
System.out.println("mouseReleased X: "+e.getX()+"mouseReleased Y: "+e.getY());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(DA_WIDTH,DA_HEIGHT);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawIntoBufferedImage();
g.drawImage(bImage,0,0,null);
freehandLines(g);
}
public void drawIntoBufferedImage()
{
Graphics g = bImage.getGraphics();
freehandLines(g);
g.dispose();
}
public void freehandLines(Graphics g)
{
if(points != null && points.size() > 1)
{
g.setColor(getCurrentColor());
for(int i = 0; i < points.size()-1;i++)
{
int x1 = points.get(i).x;
int y1 = points.get(i).y;
int x2 = points.get(i+1).x;
int y2 = points.get(i+1).y;
g.drawLine(x1, y1, x2, y2);
}
}
}
//clear drawings method
public void clearDrawings()
{
if(points!=null)
{
points.clear();
Graphics g = bImage.getGraphics();
g.setColor(DA_BGCOLOR);
g.fillRect(0, 0, DA_WIDTH, DA_WIDTH);
g.dispose();
repaint();
}
}
public void setCurrentColor(Color currentColor) {
if(currentColor == null)
{
currentColor = Color.BLACK;
}else{
this.currentColor = currentColor;
}
}
public Color getCurrentColor() {
if (currentColor == null)
return Color.BLACK;
else
return currentColor;
}
}
main class
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class STTestMain extends JFrame {
STDrawingArea drawingArea = new STDrawingArea();
public STTestMain()
{
//JFrame settings
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Spelling Trainer");
setResizable(false);
setVisible(true);
//Panel of buttons
JPanel buttonContainer = new JPanel();
JButton btnRedPen = new JButton("Red Pen");
JButton btnGreenPen = new JButton("Green Pen");
JButton btnClear = new JButton("Clear");
buttonContainer.add(btnRedPen);
buttonContainer.add(btnGreenPen);
buttonContainer.add(btnClear);
//Drawing Area instantiation
//Adding things to JFrame
getContentPane().add(drawingArea);
getContentPane().add(buttonContainer,BorderLayout.PAGE_END);
pack();
//button listener
btnRedPen.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
drawingArea.setCurrentColor(Color.RED);
}
});
btnGreenPen.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
drawingArea.setCurrentColor(Color.GREEN);
}
});
btnClear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
drawingArea.clearDrawings();
}
});
}
public static void main(String args[])
{
STTestMain test = new STTestMain();
}
}