Cannot create multiple polygons in Java - only one - java

Given the following code :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
* #author X2
*
*/
public class PolygonnerJframe
{
public static void main (String[] args)
{
JFrame frame = new JFrame("Draw polygons");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new DrawingPanel());
frame.pack();
frame.setVisible(true);
}
}
/**
* Main class
* #author X2
*
*/
class DrawingPanel extends JPanel implements MouseListener, MouseMotionListener
{
/**
*
*/
private static final long serialVersionUID = 1L;
private static final Dimension MIN_DIM = new Dimension(300, 300);
private static final Dimension PREF_DIM = new Dimension(500, 500);
private boolean polygonDone = false;
private final Point trackPoint = new Point(); // The 'dummy' point tracking the mouse
private ArrayList<Point> points = new ArrayList<Point>(); // The list of points making up a polygon
private ArrayList<Point> helper = new ArrayList<Point>(); // The list of points making up a polygon
public ArrayList<Point> copyCreate(ArrayList<Point> input , ArrayList<Point> output)
{
int i = 0;
if (output == null)
output = new ArrayList<Point>();
while (i < input.size())
{
output.add(input.get(i));
i++;
}
return output;
}
/**
* Setting the dimensions of the windows
*/
public Dimension getMinimumSize() { return MIN_DIM; }
public Dimension getPreferredSize() { return PREF_DIM; }
/**
* The only constructor needed for this class
*/
DrawingPanel()
{
super();
addMouseListener(this);
addMouseMotionListener(this);
}
/**
* The drawing itself
*/
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int numPoints = points.size();
if (numPoints == 0)
return; // nothing to draw
Point prevPoint = (Point) points.get(0);
// draw polygon
Iterator<Point> it = points.iterator();
while (it.hasNext())
{
Point curPoint = (Point) it.next();
draw(g, prevPoint, curPoint);
prevPoint = curPoint;
}
// now draw tracking line or complete the polygon
if (polygonDone == true)
{
draw(g, prevPoint, (Point) points.get(0));
}
else // polygonDone == false
draw(g, prevPoint, trackPoint);
}
/**
* MouseListener interface
*/
public void mouseClicked(MouseEvent evt)
{
int x = evt.getX();
int y = evt.getY();
switch (evt.getClickCount())
{
case 1: // single-click
if (polygonDone == true)
{
this.helper = this.copyCreate(this.points, this.helper); // copy the new coordinates into the helper
points.clear();
polygonDone = false;
}
points.add(new Point(x, y));
repaint();
break;
case 2: // double-click
polygonDone = true;
points.add(new Point(x, y));
// repaint();
break;
default: // ignore anything else
break;
}
}
/**
* MouseMotionListener interface
*/
public void mouseMoved(MouseEvent evt)
{
trackPoint.x = evt.getX();
trackPoint.y = evt.getY();
repaint();
}
/**
* draw points and lines
* #param g
* #param p1
* #param p2
*/
private void draw(Graphics g, Point p1, Point p2)
{
int x1 = p1.x;
int y1 = p1.y;
int x2 = p2.x;
int y2 = p2.y;
// draw the line first so that the points
// appear on top of the line ends, not below
g.setColor(Color.green.darker());
g.drawLine(x1 + 3, y1 + 3, x2 + 3, y2 + 3);
g.drawLine(x1 + 4, y1 + 4, x2 + 4, y2 + 4);
g.drawLine(x1 + 5, y1 + 5, x2 + 5, y2 + 5);
g.setColor(Color.green);
g.fillOval(x1, y1, 8, 8);
g.setColor(Color.black);
g.fillOval(x2, y2, 8, 8);
}
public void mouseDragged(MouseEvent evt) { /* EMPTY */ }
public void mousePressed(MouseEvent evt) { /* EMPTY */ }
public void mouseReleased(MouseEvent evt) { /* EMPTY */ }
public void mouseEntered(MouseEvent evt) { /* EMPTY */ }
public void mouseExited(MouseEvent evt) { /* EMPTY */ }
}
I can only draw one polygon each time , meaning - when I try to start a new polygon
the "old" polygon vanishes , but I don't understand why .
So how can I draw multiple polygons ?
What causes the old polygon to vanish ? I thought maybe due to repaint() , but I tried without it but it didn't help .
I'd appreciate your help

The polygons are indeed being erased by calling points.clear(). To counter this, you could to maintain co-ordinate information using the Polygon class about previous polygons in a separate List which could be painted along with the "in-progress" polygon. This is outlined in Custom Painting Approaches.

Related

How to Draw Fractal Iteratively?

I currently have a working code that draws a fractal tree using recursion. However, when I try to draw it iteratively, it is not working.
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
/*
-Used built in Math trig methods to accomodate angling...looked this up online
https://stackoverflow.com/questions/30032635/java-swing-draw-a-line-at-a-specific-angle
*/
public class Test extends JFrame {
public Test() {
setBounds(100, 100, 800, 600); //sets the boundary for drawing
}
public void drawTree(Graphics g, int x1, int y1, double angle, int depth) {
System.out.println("x");
if (depth == 6){
return; //base case here to prevent infinite recursion..
}
else {
System.out.println("y1");
//embedded portion '(Math.toRadians(angle) * depth * 10.0)'represents angle...
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0); //vertical shift calculated using the Sine...PARSED to int because method drawLine() accepts only ints as params
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0); //hor. shift calculated using the Cos..PARSED to int
// System.out.println("x2: " + x2);//will reflect the change in vertical shift
//System.out.println("y2: " + y2);//will reflect change in hor. shift
g.drawLine(x1, y1, x2, y2);//value x1 equals previous line...in other word, start at where previously left off
// notice that the end point (x2 and y2) becomes starting point for each successive call
drawTree(g, x2, y2, angle - 20, depth - 1); //DRAWS LEFT SIDE?
// drawTree(g, x2, y2, angle + 20, depth - 1); //DRAWS RIGHT SIDE?
}
if (depth == 6){
return; //base case here to prevent infinite recursion..
}
else {
System.out.println("y2");
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0); //vertical shift calculated using the Sine...PARSED to int because method drawLine() accepts only ints as params
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0); //hor. shift calculated using the Cos..PARSED to int
// System.out.println("x2: " + x2);//will reflect the change in vertical shift
//System.out.println("y2: " + y2);//will reflect change in hor. shift
g.drawLine(x1, y1, x2, y2);//value x1 equals previous line...in other word, start at where previously left off
// notice that the end point (x2 and y2) becomes starting point for each successive call
// drawTree(g, x2, y2, angle - 20, depth - 1); //DRAWS LEFT SIDE?
drawTree(g, x2, y2, angle + 20, depth - 1); //DRAWS RIGHT SIDE?
}
}
public void drawIteratively(Graphics g, int x1A, int y1A, int x1B, int y1B, double angleA, double angleB, int depthA, int depthB){
while (depthA != 4) {
int x2A = x1A + (int) (Math.cos(Math.toRadians(angleA)) * depthA * 10.0);
int y2A = y1A + (int) (Math.sin(Math.toRadians(angleA)) * depthA * 10.0);
g.drawLine(x1A, y1A, x2A, y2A); //remember it must continue drawing from where it left off
angleA = angleA - 20;
depthA = depthA - 1;
x1A = x2A;
y1A = y2A;
}
while (depthA != 4) {
int x2A = x1A + (int) (Math.cos(Math.toRadians(angleA)) * depthA * 10.0);
int y2A = y1A + (int) (Math.sin(Math.toRadians(angleA)) * depthA * 10.0);
g.drawLine(x1A, y1A, x2A, y2A); //remember it must continue drawing from where it left off
angleA = angleA - 20;
depthA = depthA - 1;
x1A = x2A;
y1A = y2A;
}
/*
while(depthB != 4){
int x2B = x1B + (int) (Math.cos(Math.toRadians(angleB)) * depthB * 10.0);
int y2B = y1B + (int) (Math.sin(Math.toRadians(angleB)) * depthB * 10.0);
g.drawLine(x1B, y1B, x2B, y2B);
angleB = angleB + 20;
depthB = depthB - 1;
x1B = x2B;
y1B = y2B;
}
*/
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLUE);
//drawTree(g, 400, 400, -90, 9); //these values corresponding to original line aka trunk during initial method call
drawIteratively(g, 400, 500, 400,500 ,-90 , -90, 9,9);
}
public static void main(String[] args) {
new Test().setVisible(true);
}
}
Ignoring the fractals math: if you want to keep the recursive drawing, warp the long process (recursive calculation) with a SwingWorker, and let it update the GUI. Here is an example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
public class RecursiveDraw extends JFrame {
private int x1A, y1A, x2A, y2A;
private final int W = 700, H = 500;
private Random random = new Random();
private Color randomColor = Color.BLUE;
private JPanel panel;
public RecursiveDraw() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
panel = new MyPanel();
add(panel, BorderLayout.CENTER);
pack();
setVisible(true);
new Task().run();
}
public void recursiveDraw(int x1A, int y1A, int depth){
if(depth > 15) { return;}
this.x1A = x1A; this.y1A = y1A;
x2A = random.nextInt(W);
y2A = random.nextInt(H);
randomColor = new Color(random.nextInt(0xFFFFFF));
panel.repaint();
try {
Thread.sleep(1000); //delay
} catch (InterruptedException ex) { ex.printStackTrace();}
recursiveDraw(x2A, y2A, ++depth );
}
class MyPanel extends JPanel{
public MyPanel() {
setPreferredSize(new Dimension(W,H));
}
#Override
public void paintComponent(Graphics g) {
//super.paintComponent(g); //requires storing all points calculated
//so they can be redrawn. recommended
g.setColor(randomColor);
g.drawLine(x1A, y1A, x2A, y2A);
}
}
class Task extends SwingWorker<Void,Void> {
#Override
public Void doInBackground() {
recursiveDraw(W/2, H/2, 0);
return null;
}
}
public static void main(String[] args) {
new RecursiveDraw();
}
}
The basic structure of iterative drawing, using Timer, as proposed by #MadProgrammer could look like this :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class TimerIterativeDraw extends JFrame {
private final static int W = 700, H = 500;
private final static int DELAY= 1000;
private final static int NUMBER_OF_DRAWS_LIMIT = 50;
private int x2A = W/2, y2A = H/2, x1A, y1A, numberOfDraws;
private Random random = new Random();
private Color randomColor = Color.BLUE;
private JPanel panel;
private Timer timer;
public TimerIterativeDraw() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
panel = new MyPanel();
add(panel, BorderLayout.CENTER);
pack();
setVisible(true);
timer = new Timer(DELAY,new Task());
timer.start();
}
public void upDateGui(){
if(numberOfDraws++ >= NUMBER_OF_DRAWS_LIMIT){
timer.stop();
}
x1A = x2A; y1A = y2A;
x2A = random.nextInt(W);
y2A = random.nextInt(H);
randomColor = new Color(random.nextInt(0xFFFFFF));
//for better implementation store all points in an array list
//so they can be redrawn
panel.repaint();
}
class MyPanel extends JPanel{
public MyPanel() {
setPreferredSize(new Dimension(W,H));
}
#Override
public void paintComponent(Graphics g) {
//super.paintComponent(g); //requires storing all points calculated
//so they can be redrawn. recommended
g.setColor(randomColor);
g.drawLine(x1A, y1A, x2A, y2A);
}
}
class Task implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
upDateGui();
}
}
public static void main(String[] args) {
new TimerIterativeDraw();
}
}
There's probably a few ways you can do this, but...
You need some kind of class which you can call which will calculate the next step and record it
You need to make sure that you're only updating the state from within the context of the Event Dispatching Thread. This is important, as you don't want to update the UI or anything the UI might rely on out side the EDT, otherwise you run the risk of race conditions and dirty paints
So, first, we need some way to create the branches in some kind of stepped manner. The idea is to only generate a new branch each time the class is told to update.
The class will contain it's only state and management, but will provide access to a List of points which it has created, maybe something like...
public class Generator {
private List<Point> points;
private double angle;
private double delta;
private int depth = 9;
private Timer timer;
public Generator(Point startPoint, double startAngle, double delta) {
points = new ArrayList<>(25);
points.add(startPoint);
angle = startAngle;
this.delta = delta;
}
public List<Point> getPoints() {
return new ArrayList<Point>(points);
}
public boolean tick() {
Point next = updateTree(points.get(points.size() - 1), angle);
angle += delta;
depth--;
if (next != null) {
points.add(next);
}
return next != null;
}
public Point updateTree(Point p, double angle) {
if (depth == 6) {
return null;
}
System.out.println("depth = " + depth + "; angle = " + angle);
//embedded portion '(Math.toRadians(angle) * depth * 10.0)'represents angle...
int x2 = p.x + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0); //vertical shift calculated using the Sine...PARSED to int because method drawLine() accepts only ints as params
int y2 = p.y + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0); //hor. shift calculated using the Cos..PARSED to int
return new Point(x2, y2);
}
}
Now, this class only generates a single branch, in order to make a tree, you will need two instances of this class, with different deltas
Next, we need someway to ask this generator to generate the next step on a regular bases. For me, this typically invokes using a Swing Timer.
The reason been:
It's simple. Seriously, it's really simple
It won't block the EDT, thus not freezing the UI
It updates within the context of the EDT, making it safe to update the state of the UI from within.
Putting these two things together into a simple JPanel which controls the Timer and paints the points...
public class TestPane extends JPanel {
private Generator left;
private Generator right;
public TestPane() {
Point startPoint = new Point(200, 400);
left = new Generator(startPoint, -90, -20);
right = new Generator(startPoint, -90, 20);
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
boolean shouldContinue = left.tick() && right.tick();
if (!shouldContinue) {
((Timer)(e.getSource())).stop();
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
render(g2d, left.getPoints());
g2d.setColor(Color.BLUE);
render(g2d, right.getPoints());
g2d.dispose();
}
protected void render(Graphics2D g2d, List<Point> points) {
Point start = points.remove(0);
while (points.size() > 0) {
Point end = points.remove(0);
g2d.draw(new Line2D.Double(start, end));
start = end;
}
}
}

I need help on moving the small box created to move smoothly as I click and drag near the outside layer. Here is my code: [duplicate]

I made a mini code that draw oval and link each other , now i try to move the oval(Circle) but I have a problem (in coding)
// Panneau.java
public class Panneau extends JPanel {
private int R = 20;
private boolean isDrag = false;
String text = "stack";
int x = 250, y = 200;
int height = 50, width = 50;
Random Rnd = new Random();
int rand=Rnd.nextInt();
int r=Math.abs(rand%250);
int r2=Math.abs(rand%250);
public Panneau() {
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if ((x<=e.getX() && x+R>=e.getX()) && ( y<=e.getY() && y+R>=e.getY())) {
moveVertex(e.getX(),e.getY());
isDrag = true;
}
}
#Override
public void mouseReleased(MouseEvent e) {
isDrag = false;
}
});
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (isDrag) moveVertex(e.getX(),e.getY());
}
});
}
private void moveVertex(int x1, int y1) {
if ((x!=x1) || (y!=y1)) {
x=x1-10;
y=y1-10;
repaint();
}
}
#Override
protected void paintComponent(Graphics g){
// declaration
super.paintComponent(g);
g.setColor(Color.black);
g.drawLine(x,y,x+r,y+r2);
g.setColor(Color.yellow);
g.fillOval(x-height/2, y-width/2,width, height);
g.fillOval((x-height/2)+r, (y-width/2)+r2,width, height);
FontMetrics fm = g.getFontMetrics();
double textWidth = fm.getStringBounds(text, g).getWidth();
g.setColor(Color.blue);
g.drawString(text, (int) (x - textWidth/2),(int) (y + fm.getMaxAscent() / 2));
g.drawString(text, (int) (x - textWidth/2)+r,(int) (y + fm.getMaxAscent() / 2)+r2);
}
}
I must move the two circles and the line must not move(Graph node)
please help me and thanks :)
After the update ( thanks to MadProgrammer) now I can move all the figure ( but if I clicked in the red circle only) , I want to move just circles thanks :)
Basically, because instead of using reapint(int, int) you could use repaint()
private void moveVertex(int x1, int y1) {
int OFFSET = 1;
if ((x != x1) || (y != y1)) {
x = x1 - 10;
y = y1 - 10;
repaint();
}
}
This will ensure that the entire component is repainted.
While I wouldn't discount the use of repaint(int, int), because your painting process is relatively simple, it's not going to provide you with a great deal of benefit at this stage
Updated with additional example
IF I understand, you want to be able to move a single node and have the line remain joined.
While it might be possible to implement within the code you have available, a simpler soltution would be to take advantage of the 2D Graphics Shape API, this provides a number of really useful functions, including determining of points fall within a given shape.
It also means you don't need to keep track of a large number of parameters, but instead, get a self contained object that just knows how it should be painted...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
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.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestGraphNode {
public static void main(String[] args) {
new TestGraphNode();
}
public TestGraphNode() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Panneau());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Panneau extends JPanel {
private int radius = 50;
private String text = "stack";
private List<Ellipse2D> nodes;
private Ellipse2D dragged;
private Point offset;
public Panneau() {
nodes = new ArrayList<>(25);
nodes.add(new Ellipse2D.Float(50 - (radius / 2), 100 - (radius / 2), radius, radius));
nodes.add(new Ellipse2D.Float(350 - (radius / 2), 100 - (radius / 2), radius, radius));
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
for (Ellipse2D node : nodes) {
if (node.contains(e.getPoint())) {
System.out.println("Clicked...");
dragged = node;
// Adjust for the different between the top/left corner of the
// node and the point it was clicked...
offset = new Point(node.getBounds().x - e.getX(), node.getBounds().y - e.getY());
// Highlight the clicked node
repaint();
break;
}
}
}
#Override
public void mouseReleased(MouseEvent e) {
// Erase the "click" highlight
if (dragged != null) {
repaint();
}
dragged = null;
offset = null;
}
});
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (dragged != null && offset != null) {
// Adjust the position of the drag point to allow for the
// click point offset
Point to = e.getPoint();
to.x += offset.x;
to.y += offset.y;
// Modify the position of the node...
Rectangle bounds = dragged.getBounds();
bounds.setLocation(to);
dragged.setFrame(bounds);
// repaint...
repaint();
}
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
// declaration
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
// Draw the connecting lines first
// This ensures that the lines are under the nodes...
Point p = null;
for (Ellipse2D node : nodes) {
g2d.setColor(Color.BLACK);
Point to = node.getBounds().getLocation();
to.x += radius / 2;
to.y += radius / 2;
if (p != null) {
g2d.draw(new Line2D.Float(p, to));
}
p = to;
}
// Draw the nodes...
for (Ellipse2D node : nodes) {
g2d.setColor(Color.yellow);
g2d.fill(node);
if (node == dragged) {
g2d.setColor(Color.BLUE);
g2d.draw(node);
}
g2d.setColor(Color.BLUE);
FontMetrics fm = g.getFontMetrics();
int textWidth = fm.stringWidth(text);
int x = node.getBounds().x;
int y = node.getBounds().y;
int width = node.getBounds().width;
int height = node.getBounds().height;
g.drawString(text,
x + ((width - textWidth)) / 2,
y + ((height - fm.getHeight()) / 2) + fm.getAscent());
}
g2d.dispose();
}
}
}

How to implement saving function to my "saving button" in my drawing program?

So as you can see my painting program is working properly. It can draw shapes like oval and rectangle (oval shape looks kinda bug though if anyone could help me fix it as well). I want to know how to make a saving button. Right now, I don't even know what I'm doing. I have been research on how to save a drawn image, but none of the code on internet has an example of a java made drawing program with saving function. So here's my code:
Shapeframe class
package com.comp2526.assign2c.a.a00892238;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileWriter;
import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* This class creates the painting program's toolbar, buttons and stuffs.
* #author Fu Han
* #version 1.0
*/
public class ShapeFrame extends JFrame implements ActionListener {
/**
* the white board
*/
static DrawPad drawboard;
/**
* the constant string 'save'.
*/
static final private String SAVE = "Save";
/**
* the constant string 'save as'.
*/
static final private String SAVE_AS = "Save As";
/**
* the constant string 'new'.
*/
static final private String NEW = "New";
/**
* the constant string 'color'.
*/
static final private String color = "Color";
/**
* string oval for easy access for buttons.
*/
static String oval = new String("oval");
/**
* string line for easy access for buttons.
*/
static String line = new String("line");
/**
* string rectangle for easy access for buttons.
*/
static String rectangle = new String("rectangle");
/**
* string square for easy access for buttons.
*/
static String square = new String("square");
/**
* color.
*/
Color currentColor;
/**
* ShapeFrame constructor.
*/
public ShapeFrame(){
super();
}
/**
* method that add buttons.
* #param toolBar Jtoolbar.
* #param btn Jbuttons.
*/
protected void addButtons(JToolBar toolBar, JButton btn) {
toolBar.add(btn);
}
/**
* method that add radio buttons.
* #param toolBar Jtoolbar.
* #param btn JRadioButton.
*/
protected void addRadioButtons(JToolBar toolBar, JRadioButton btn) {
toolBar.add(btn);
}
/**
* method that creates button.
* #param btnNam button name.
* #param actionCommand calling from string constant.
* #param toolTipText the message that will appear if cursor was hover over.
* #param altText alternative text.
* #return button Jbutton.
*/
protected JButton btnmaker(String btnNam, String actionCommand, String toolTipText, String altText) {
//Create and initialize the button.
JButton button = new JButton(btnNam);
button.setActionCommand(actionCommand);
button.setToolTipText(toolTipText);
button.addActionListener(this);
return button;
}
/**
* action performed when clicked button.
* #param e mouse click.
*/
public void actionPerformed(ActionEvent e) {
}
public static void savebtn(DrawPad dp) {
DrawPad dp1 = dp;
//String sb = "gg";
/*
public void save() throws IOException{
ImageIO.write(paintImage, "PNG", new File("filename.png"));
}*/
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("/home/me/Documents"));
int retrieval = chooser.showSaveDialog(null);
if (retrieval == JFileChooser.APPROVE_OPTION) {
try {
//FileWriter fw = new FileWriter(chooser.getSelectedFile()+".png");
//fw.write(sb.toString());
//fw.close();
ImageIO.write((RenderedImage) dp1.image, "PNG", new File("filename.png"));
ImageIo.
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* editlistener for menu bar.
* #author Fu Han
*
*/
private class EditListener implements ActionListener {
/**
* action performed when clicking menu button.
* #param e mouse click.
*/
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand() == SAVE) {
System.out.print("save");
}else{
System.out.println(e.getActionCommand());
}
}
}
/**
* radio listener for the radio buttons.
* #author Fu Han
*
*/
private class RadioListener implements ActionListener{
/**
* action performed when click the button.
* #param e mouse click.
*/
public void actionPerformed(ActionEvent e) {
System.out.print("ActionEvent received: ");
if (e.getActionCommand() == oval) {
System.out.println(oval + " pressed.");
drawboard.line = false;
drawboard.rectangle = false;
drawboard.square = false;
drawboard.oval = true;
}else if(e.getActionCommand() == rectangle){
System.out.println(rectangle + " pressed.");
drawboard.line = false;
drawboard.rectangle = true;
drawboard.square = false;
drawboard.oval = false;
}else if(e.getActionCommand() == square){
System.out.println(square + " pressed.");
drawboard.line = false;
drawboard.rectangle = false;
drawboard.square = true;
drawboard.oval = false;
}else{
System.out.println(line + " pressed.");
drawboard.line = true;
drawboard.rectangle = false;
drawboard.square = false;
drawboard.oval = false;
}
}
}
/**
* method for when changes of states that happened after clicking.
* #param e mouse click.
*/
public void stateChanged(ChangeEvent e) {
}
/**
* method for selecting color.
*/
private void selectColor(){
Color newColor = JColorChooser.showDialog(
ShapeFrame.this,
"Choose New Background Color",
currentColor);
if(newColor != null){
currentColor = newColor;
}
}
/**
* GUI initialization.
*/
public void init(){
Container content = getContentPane();
//Creates a new container
content.setLayout(new BorderLayout());
//sets the layout
final DrawPad drawPad = new DrawPad();
//creates a new padDraw, which is pretty much the paint program
content.add(drawPad, BorderLayout.CENTER);
JMenuBar menubar = new JMenuBar();
EditListener l = new EditListener();
JMenu filem = new JMenu("File");
JMenuItem mi;
mi = filem.add(new JMenuItem("New", 'n'));
mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK));
mi.addActionListener(l);
mi = filem.add(new JMenuItem("Open", 'o'));
mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Event.CTRL_MASK));
mi.addActionListener(l);
mi = filem.add(new JMenuItem("Save", 's'));
mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Event.CTRL_MASK));
mi.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
savebtn(drawPad);
}
});
mi = filem.add(new JMenuItem("Save As", 'a'));
mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK));
mi.addActionListener(l);
mi = filem.add(new JMenuItem("Exit", 'e'));
mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, Event.CTRL_MASK));
mi.addActionListener(l);
JMenu shapem = new JMenu("Shape");
JMenuItem smi;
smi = shapem.add(new JMenuItem("Line", 'l'));
smi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK));
smi.addActionListener(l);
smi = shapem.add(new JMenuItem("Circle", 'c'));
smi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Event.CTRL_MASK));
smi.addActionListener(l);
smi = shapem.add(new JMenuItem("Rectangle", 'r'));
smi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, Event.CTRL_MASK));
smi.addActionListener(l);
smi = shapem.add(new JMenuItem("Square", 'q'));
smi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, Event.CTRL_MASK));
smi.addActionListener(l);
smi = shapem.add(new JMenuItem("Shape Picker", 'p'));
smi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, Event.CTRL_MASK));
smi.addActionListener(l);
menubar.add(filem);
menubar.add(shapem);
menubar.add(Box.createHorizontalGlue());
setJMenuBar(menubar);
//Create the toolbar.
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
JButton saveBtn = btnmaker("Save",SAVE, "save your paint", "Save");
JButton saveAsBtn = btnmaker("Save As",SAVE_AS, "save your paint to?","Save As");
JButton NewBtn = btnmaker("New",NEW,"new paint","New");
JButton colorbtn = btnmaker("Color",color,"choose color","Color");
colorbtn.setToolTipText("Click this button to select colors.");
colorbtn.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg) {
selectColor();
drawPad.color(currentColor);
}
});
RadioListener myListener = new RadioListener();
JRadioButton ovalShape = new JRadioButton(oval);
ovalShape.addActionListener(myListener);
ovalShape.setMnemonic(KeyEvent.VK_A);
ovalShape.setActionCommand(oval);
//add(ovalShape);
JRadioButton rectangleShape = new JRadioButton(rectangle);
rectangleShape.addActionListener(myListener);
rectangleShape.setMnemonic(KeyEvent.VK_A);
rectangleShape.setActionCommand(rectangle);
//add(rectangleShape);
JRadioButton squareShape = new JRadioButton(square);
squareShape.addActionListener(myListener);
squareShape.setMnemonic(KeyEvent.VK_A);
squareShape.setActionCommand(square);
//add(squareShape);
JRadioButton lineShape = new JRadioButton(line);
lineShape.addActionListener(myListener);
lineShape.setMnemonic(KeyEvent.VK_B);
lineShape.setActionCommand(line);
lineShape.setSelected(true);
//add(lineShape);
ButtonGroup group = new ButtonGroup();
group.add(ovalShape);
group.add(lineShape);
group.add(rectangleShape);
group.add(squareShape);
JToolBar toolBar = new JToolBar("File");
JToolBar toolBar2 = new JToolBar("Shape",JToolBar.VERTICAL);
JToolBar toolbar3 = new JToolBar("colors",JToolBar.VERTICAL);
addButtons(toolBar,saveBtn);
addButtons(toolBar,saveAsBtn);
addButtons(toolBar,NewBtn);
addRadioButtons(toolBar2,ovalShape);
addRadioButtons(toolBar2,lineShape);
addRadioButtons(toolBar2,rectangleShape);
addRadioButtons(toolBar2,squareShape);
addButtons(toolbar3,colorbtn);
panel.add(toolBar);
panel2.add(toolBar2);
panel2.add(toolbar3);
content.add(panel, BorderLayout.NORTH);
content.add(panel2, BorderLayout.WEST);
}
}
DrawPad class:
package com.comp2526.assign2c.a.a00892238;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import javax.swing.JComponent;
/**
* the draw pad class for drawing
* #author Fu Han
* #version 1.0
*/
class DrawPad extends JComponent{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* image
*/
Image image;
/**
* what user will be using to draw on
*/
Rectangle r = null;
Oval o = null;
Graphics2D graphics2D;
ArrayList<Rectangle> rectangleList = null;
/**
*mouse coordinates
*/
static boolean rectangle = false;
static boolean oval = false;
static boolean line = false;
static boolean square = false;
int currentX, currentY, oldX, oldY;
/**
* shape object
*/
/**
* constructor
*/
public DrawPad(){
rectangleList = new ArrayList<Rectangle>();
setDoubleBuffered(false);
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
oldX = e.getX();
oldY = e.getY();
if(rectangle == true){
r = new Rectangle(e.getX(), e.getY(),
e.getX(), e.getY(), graphics2D.getColor());
}else if(oval == true){
o = new Oval(e.getX(), e.getY(),
e.getX(), e.getY(), graphics2D.getColor());
}
}
});
//if the mouse is pressed it sets the oldX & oldY
//coordinates as the mouses x & y coordinates
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
currentX = e.getX();
currentY = e.getY();
if(graphics2D != null){
if(rectangle == true){
r = new Rectangle(r.getX1(),
r.getY1(), e.getX(), e.getY(),
r.getColor());
drawRectangle(r,graphics2D);
rectangleList.add(new Rectangle(r.getX1(),
r.getY1(), e.getX(), e.getY(),
graphics2D.getColor()));
repaint();
oval = false;
line = false;
square = false;
}
else if(line == true){
graphics2D.drawLine(oldX, oldY, currentX, currentY);
repaint();
oldX = currentX;
oldY = currentY;
rectangle = false;
oval = false;
square = false;
}
else if(oval == true){
o = new Oval(o.getX1(), o.getY1(),
e.getX(), e.getY(), o.getColor());
drawOval(o,graphics2D);
repaint();
rectangle = false;
square = false;
line = false;
}
}
}
});
//while the mouse is dragged it sets currentX & currentY as the mouses x and y
//then it draws a line at the coordinates
//it repaints it and sets oldX and oldY as currentX and currentY
}
/**
* painting dot
* #param g Graphic
*/
public void paintComponent(Graphics g){
if(image == null){
image = createImage(getSize().width, getSize().height);
graphics2D = (Graphics2D)image.getGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, null);
}
public void clear(){
graphics2D.setPaint(Color.white);
graphics2D.fillRect(0, 0, getSize().width, getSize().height);
graphics2D.setPaint(Color.black);
repaint();
}
public void drawRectangle(Rectangle rek, Graphics gr) {
Graphics2D g = null;
if (gr instanceof Graphics2D) {
g = (Graphics2D) gr;
}
else{ return; }
//g.setStroke(new BasicStroke(3));
g.drawRect(rek.getX1(), rek.getY1(), rek.getWidth(), rek.getHeight());
g.setColor(graphics2D.getColor());
g.fillRect(rek.getX1(), rek.getY1(), rek.getWidth(), rek.getHeight());
//g.drawLine(rek.getX1(), rek.getY1(), rek.getX2(), rek.getY1());
//g.drawLine(rek.getX1(), rek.getY1(), rek.getX1(), rek.getY2());
//g.drawLine(rek.getX2(), rek.getY2(), rek.getX2(), rek.getY1());
// g.drawLine(rek.getX2(), rek.getY2(), rek.getX1(), rek.getY2());
}
public void drawOval(Oval ovo, Graphics gr) {
Graphics2D g = null;
if (gr instanceof Graphics2D) {
g = (Graphics2D) gr;
}
else{ return; }
//g.setStroke(new BasicStroke(3));
g.drawOval(ovo.getX1(), ovo.getY1(), ovo.getWidth(), ovo.getHeight());
g.setColor(graphics2D.getColor());
g.fillOval(ovo.getX1(), ovo.getY1(), ovo.getWidth(), ovo.getHeight());
//g.drawLine(rek.getX1(), rek.getY1(), rek.getX2(), rek.getY1());
//g.drawLine(rek.getX1(), rek.getY1(), rek.getX1(), rek.getY2());
//g.drawLine(rek.getX2(), rek.getY2(), rek.getX2(), rek.getY1());
// g.drawLine(rek.getX2(), rek.getY2(), rek.getX1(), rek.getY2());
}
/**
* setting dot color
* #param color color
*/
public void color(Color color){
graphics2D.setPaint(color);
repaint();
}
}
Main class:
package com.comp2526.assign2c.a.a00892238;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import javax.swing.JFrame;
/**
* main class.
* #author Fu Han
* #version 1.0
*
*/
public class Main {
/**
* tookit
*/
private static final Toolkit TOOLKIT;
static {
TOOLKIT = Toolkit.getDefaultToolkit();
}
/**
* defaulth constructor.
*/
private Main() {}
/**
* main method.
* #param argv argv
*/
public static void main(final String[] argv) {
final ShapeFrame frame;
frame = new ShapeFrame();
position(frame);
frame.init();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
/**
* position for shapeframe.
* #param frame Shapeframe.
*/
private static void position(final JFrame frame) {
final Dimension size;
size = calculateScreenArea(0.80f,
0.80f);
frame.setSize(size);
frame.setLocation(centreOnScreen(size));
}
/**
* the amount of center on screen
* #param size space size.
* #return the complete calculated space.
*/
public static Point centreOnScreen(final Dimension size) {
final Dimension screenSize;
if (size == null) {
throw new IllegalArgumentException("Size cannot be null");
}
screenSize = TOOLKIT.getScreenSize();
return (new Point((screenSize.width - size.width) / 2, (screenSize.height - size.height) / 2));
}
/**
* method that calculating screen area.
* #param widthPercent width percentage.
* #param heightPercent height percentage.
* #return dimension the dimension.
*/
public static Dimension calculateScreenArea(final float widthPercent,
final float heightPercent) {
final Dimension screenSize;
final Dimension area;
final int width;
final int height;
final int size;
if ((widthPercent <= 0.0f) || (widthPercent > 100.0f)) {
throw new IllegalArgumentException("widthPercent cannot be " +
"<= 0 or > 100 - got: " +
widthPercent);
}
if ((heightPercent <= 0.0f) || (heightPercent > 100.0f)) {
throw new IllegalArgumentException("heightPercent cannot be " +
"<= 0 or > 100 - got: " +
heightPercent);
}
screenSize = TOOLKIT.getScreenSize();
width = (int)(screenSize.width * widthPercent);
height = (int)(screenSize.height * heightPercent);
size = Math.min(width,
height);
area = new Dimension(size,
size);
return (area);
}
}
Rectangle class:
package com.comp2526.assign2c.a.a00892238;
import java.awt.Color;
import java.awt.Graphics2D;
public class Rectangle extends Shape {
// Initialize variables
private int x1; // x coordinate of first endpoint
private int y1; // y coordinate of first endpoint
private int x2; // x coordinate of second endpoint
private int y2; // y coordinate of second endpoint
private Color colour; // colour of the shape
// A no-parameter constructor that sets all the coordinates of the shape to
// 0 and the
// colour to Color.BLACK
public Rectangle() {
x1 = 0;
y1 = 0;
x2 = 0;
y2 = 0;
colour = Color.BLACK;
}
// A constructor that initializes the coordinates and colour to the values
// of the
// parameters supplied.
public Rectangle(int x1, int y1, int x2, int y2, Color col) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.colour = col;
}
public void setX1(int x1) {
this.x1 = x1;
}
public void setY1(int y1) {
this.y1 = y1;
}
public void setX2(int x2) {
this.x2 = x2;
}
public void setY2(int y2) {
this.y2 = y2;
}
public void setColor(Color colour) {
this.colour = colour;
}
public int getX1() {
return this.x1;
}
public int getY1() {
return this.y1;
}
public int getX2() {
return this.x2;
}
public int getY2() {
return this.y2;
}
public Color getColor() {
return this.colour;
}
public int getWidth() {
return (Math.abs(x2 - x1));
}
public int getHeight() {
return (Math.abs(y2 - y1));
}
public int getUpperLeftX() {
return (Math.min(x1, x2));
}
public int getUpperLeftY() {
return (Math.min(y1, y2));
}
}
Point class:
package com.comp2526.assign2c.a.a00892238;
public class Point {
private int x = 0;
private int y = 0;
public Point() {}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Oval class:
package com.comp2526.assign2c.a.a00892238;
import java.awt.Color;
import java.awt.Graphics2D;
public class Oval {
// Initialize variables
private int x1; // x coordinate of first endpoint
private int y1; // y coordinate of first endpoint
private int x2; // x coordinate of second endpoint
private int y2; // y coordinate of second endpoint
private Color colour; // colour of the shape
// A no-parameter constructor that sets all the coordinates of the shape to
// 0 and the
// colour to Color.BLACK
public Oval() {
x1 = 0;
y1 = 0;
x2 = 0;
y2 = 0;
colour = Color.BLACK;
}
// A constructor that initializes the coordinates and colour to the values
// of the
// parameters supplied.
public Oval(int x1, int y1, int x2, int y2, Color col) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.colour = col;
}
public void setX1(int x1) {
this.x1 = x1;
}
public void setY1(int y1) {
this.y1 = y1;
}
public void setX2(int x2) {
this.x2 = x2;
}
public void setY2(int y2) {
this.y2 = y2;
}
public void setColor(Color colour) {
this.colour = colour;
}
public int getX1() {
return this.x1;
}
public int getY1() {
return this.y1;
}
public int getX2() {
return this.x2;
}
public int getY2() {
return this.y2;
}
public Color getColor() {
return this.colour;
}
public int getWidth() {
return (Math.abs(x2 - x1));
}
public int getHeight() {
return (Math.abs(y2 - y1));
}
public int getUpperLeftX() {
return (Math.min(x1, x2));
}
public int getUpperLeftY() {
return (Math.min(y1, y2));
}
}
In your ShapeFrame class if you make your savebtn() method like this then your File->Save option will save the image where you pick from the save dialog, the other buttons and such you have to do but your File->Save option will save the file with this
public static void savebtn(DrawPad dp) {
DrawPad dp1 = dp;
//String sb = "gg";
/*
public void save() throws IOException{
ImageIO.write(paintImage, "PNG", new File("filename.png"));
}*/
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("/home/me/Documents"));
int retrieval = chooser.showSaveDialog(null);
if (retrieval == JFileChooser.APPROVE_OPTION) {
try {
//FileWriter fw = new FileWriter(chooser.getSelectedFile()+".png");
//fw.write(sb.toString());
//fw.close();
File f = chooser.getSelectedFile();
String filePath = f.getPath();
if(!filePath.toLowerCase().endsWith(".png"))
{
f = new File(filePath + ".png");
}
ImageIO.write((RenderedImage) dp1.image, "PNG", f);
//ImageIo.
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

How to drop a ball when clicked with mouse?

I'm working on a game project. The aim is clicking the balls and drop them into the basket which is below in the JPanel. I created some ways to do that but I can't achieve it. In my opinion, when the user click the ball's center with a margin of error (because the program can't catch the real point of balls), the program understands the action and runs the function of this issue. After clicking the ball it should be dropped down straight but the other balls should be continued. I use MouseListener#mousePressed method, but it doesn't work or I'm missing some parts. In addition, I made some changes in my source code, but I want to listen your advices so I am writing this topic.
I wrote a method which finds the mouse and ball coordinates. So when I make some changes to it, I can achieve my project goal. You can see the editing in the picture.
This is my source code ;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Game {
public Game() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager
.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException
| UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("MultipleBallApp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new BallControl());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BallControl extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private BallPanel ballPanel = new BallPanel();
private JButton Suspend = new JButton("Suspend");
private JButton Resume = new JButton("Resume");
private JButton Add = new JButton("+1");
private JButton Subtract = new JButton("-1");
private JScrollBar Delay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(Suspend);
panel.add(Resume);
panel.add(Add);
panel.add(Subtract);
// Add ball and buttons to the panel
ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
Delay.setOrientation(JScrollBar.HORIZONTAL);
ballPanel.setDelay(Delay.getMaximum());
setLayout(new BorderLayout());
add(Delay, BorderLayout.NORTH);
add(ballPanel, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
this.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent clickEvent) {
// TODO Auto-generated method stub
System.out.println("X coordinate =" + clickEvent.getX());
System.out.println("Y coordinate = " + clickEvent.getY());
double radius1;
int x = 0;
double y = 0;
int radius = 15;
double xM = clickEvent.getX();
double yM = clickEvent.getY();
radius1 = Math.sqrt((xM - x) * (xM - x) + (yM - y)
* (yM - y));
System.out.println("Radius1 =" + radius1);
// ballPanel.list.get(0).setD
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
});
// Register listeners
Suspend.addActionListener(new Listener());
Resume.addActionListener(new Listener());
Add.addActionListener(new Listener());
Subtract.addActionListener(new Listener());
Delay.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
ballPanel.setDelay(Delay.getMaximum() - e.getValue());
}
});
}
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Suspend) {
ballPanel.suspend();
} else if (e.getSource() == Resume) {
ballPanel.resume();
} else if (e.getSource() == Add) {
ballPanel.add();
} else if (e.getSource() == Subtract) {
ballPanel.subtract();
}
}
}
}
class BallPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private int delay = 30;
public ArrayList<AnimatedShape> list = new ArrayList<AnimatedShape>();
private AnimatedRectange rectangle;
public BallPanel() {
this.rectangle = new AnimatedRectange(-25, 373, 50, 25, Color.BLACK);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Create a timer with the initial delay
protected Timer timer = new Timer(delay, new ActionListener() {
/**
* Handle the action event
*/
#Override
public void actionPerformed(ActionEvent e) {
for (AnimatedShape ball : list) {
ball.update(getBounds());
}
rectangle.update(getBounds());
repaint();
}
});
public void add() {
int radius = 15;
// Randomised position
int x = (int) (Math.random() * (getWidth() - (radius * 2)))
+ radius;
int y = (int) (Math.random() * (getHeight() - (radius * 2)))
+ radius;
Color color = new Color((int) (Math.random() * 256),
(int) (Math.random() * 256), (int) (Math.random() * 256));
AnimatedBall ball = new AnimatedBall(x, y, radius, color);
list.add(ball);
}
// public void formula(MouseEvent clickEvent) {
// double radius1;
// int x = 0;
// double y = 0;
// int radius = 15;
// double xM = clickEvent.getX();
// double yM = clickEvent.getY();
// radius1 = Math.sqrt((xM - x) * (xM - x) + (yM - y) * (yM - y));
// System.out.println("Radius1 =" + radius1);
// }
public void subtract() {
if (list.size() > 0) {
list.remove(list.size() - 1); // Remove the last ball
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (AnimatedShape ball : list) {
ball.paint(this, g2d);
}
rectangle.paint(this, g2d);
}
public void suspend() {
timer.stop();
}
public void resume() {
timer.start();
}
public void setDelay(int delay) {
this.delay = delay;
timer.setDelay(delay);
}
}
public interface AnimatedShape {
public void update(Rectangle bounds);
public void paint(JComponent parent, Graphics2D g2d);
}
public abstract class AbstractAnimatedShape implements AnimatedShape {
private Rectangle bounds;
private int dx, dy;
public AbstractAnimatedShape() {
}
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
public Rectangle getBounds() {
return bounds;
}
public int getDx() {
return dx;
}
public int getDy() {
return dy;
}
public void setDx(int dx) {
this.dx = dx;
}
public void setDy(int dy) {
this.dy = dy;
}
#Override
public void update(Rectangle parentBounds) {// ball
Rectangle bounds = getBounds();
int dx = getDx();
int dy = getDy();
bounds.x += dx;
bounds.y += dy;
if (bounds.x < parentBounds.x) {
bounds.x = parentBounds.x;
setDx(dx *= -1);
} else if (bounds.x + bounds.width > parentBounds.x
+ parentBounds.width) {
bounds.x = parentBounds.x + (parentBounds.width - bounds.width);
setDx(dx *= -1);
}
if (bounds.y < parentBounds.y) {
bounds.y = parentBounds.y;
setDy(dy *= -1);
} else if (bounds.y + bounds.height > parentBounds.y
+ parentBounds.height) {
bounds.y = parentBounds.y
+ (parentBounds.height - bounds.height);
setDy(dy *= -1);
}
}
}
public class AnimatedBall extends AbstractAnimatedShape {
private Color color;
public AnimatedBall(int x, int y, int radius, Color color) {
setBounds(new Rectangle(x, y / 2, radius * 2, radius * 2));
this.color = color;
setDx(Math.random() > 0.5 ? 2 : -2);
// setDy(Math.random() > 0.5 ? 2 : -2);
}
public Color getColor() {
return color;
}
#Override
public void paint(JComponent parent, Graphics2D g2d) {
Rectangle bounds = getBounds();
g2d.setColor(getColor());
g2d.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
}
}
public class AnimatedRectange extends AbstractAnimatedShape {
private Color color;
public AnimatedRectange(int x, int y, int width, int height, Color color) {
setBounds(new Rectangle(x, y, width, height));
this.color = color;
setDx(2);
}
// Don't want to adjust the vertical speed
#Override
public void setDy(int dy) {
}
#Override
public void paint(JComponent parent, Graphics2D g2d) {
Rectangle bounds = getBounds();
g2d.setColor(color);
g2d.fill(bounds);
}
}
/**
* Main method
*/
public static void main(String[] args) {
new Game();
}
}
At the end of your mousePressed method, you can go though all AnimatedShape objects, check whether they are an AnimatedBall. When the object is a ball, you can test whether the mouse click hits the ball. The mouse click hits the ball when the distance between the center of the ball and the mouse position is smaller than the ball radius. When the ball is hit, you can set its horizontal speed to 0, and the vertical speed to 5 or so.
for (AnimatedShape as : ballPanel.list)
{
if (as instanceof AnimatedBall)
{
AnimatedBall ball = (AnimatedBall)as;
Rectangle b = ball.getBounds();
int ballCenterX = b.x + b.width / 2;
int ballCenterY = b.y + b.height / 2;
Point p = new Point(ballCenterX, ballCenterY);
double d = p.distance(clickEvent.getPoint());
if (d < radius)
{
ball.setDx(0);
ball.setDy(5);
}
}
}
Note
In order to make this work properly, you have to attach this listener to the ballPanel. Originally, you had the line
this.addMouseListener(new MouseListener() {
in your code. You have to change this to
ballPanel.addMouseListener(new MouseListener() {
Otherwise, the mouse coordinates will refer to the wrong component!
Concerning the question from the comment
how can I stop and disapper clickedball's when they crash the bound
You may probably insert method to check this, and call this method in the actionPerformed method of your timer. Further explainations are probably beyond the scope of an anser on a Q&A site. Stackoverflow is not a homework-solution-generator.

Letting user draw a rectangle with mouse in Java

I'm writing a program that lets the user draw a hollow rectangle on the screen on top of an image. They can also click on the image and the clicks are joined up to form polygons.
Joining up points works fine, but when the user drags to draw a rectangle, the previously drawn rectangles and polygons disappear. The runnable code is below;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageLabeller extends JFrame {
static boolean drawRectangle = false;
/**
* some java stuff to get rid of warnings
*/
private static final long serialVersionUID = 1L;
/**
* main window panel
*/
JPanel appPanel = null;
/**
* toolbox - put all buttons here
*/
JPanel toolboxPanel = null;
/**
* image panel - displays image and editing area
*/
static ImagePanel imagePanel;
/**
* handles New Object button action
*/
public ImageLabeller(String imageFilename) {
try {
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
System.out.println("Bye bye!");
System.exit(0);
}
});
// Create and set up the image panel.
// setup main window panel
setExtendedState(Frame.MAXIMIZED_BOTH);
appPanel = new JPanel();
appPanel.setLayout(new BoxLayout(appPanel, BoxLayout.Y_AXIS));
this.setContentPane(appPanel);
imagePanel = new ImagePanel(imageFilename);
imagePanel.setOpaque(true); // content panes must be opaque
imagePanel.setBorder(BorderFactory.createLineBorder(Color.green));
// create toolbox panel
toolboxPanel = new JPanel();
toolboxPanel.setBorder(BorderFactory.createLineBorder(Color.black));
JButton newPolyButton = new JButton("New object");
newPolyButton.setMnemonic(KeyEvent.VK_N);
// newPolyButton.setSize(50, 20);
newPolyButton.setToolTipText("Click to add new object");
newPolyButton.addActionListener(new DrawListener());
JButton newSquareButton = new JButton("New Square");
newSquareButton.setMnemonic(KeyEvent.VK_S);
// newPolyButton.setSize(50, 20);
newSquareButton.setEnabled(true);
newSquareButton.setToolTipText("Click to add new square");
newSquareButton.addActionListener(new SquareListener());
// add all buttons to toolboxPanel
toolboxPanel.add(newPolyButton);
toolboxPanel.add(newSquareButton);
// add all panels to appPanel
appPanel.add(toolboxPanel);
appPanel.add(imagePanel);
// appPanel.add(Box.createRigidArea(new Dimension(0,10)));
// display all the stuff
this.pack();
this.setVisible(true);
} catch (Exception e) {
System.err.println("Image: ");
e.printStackTrace();
}
}
public static void addNewPolygon() {
imagePanel.addNewPolygon();
}
public static void addNewRectangle() {
//imagePanel.addNewRectangle();
}
static class DrawListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
addNewPolygon();
}
}
static class SquareListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
drawRectangle = true;
imagePanel.drawingRectangle = true;
System.out.println(imagePanel.drawingRectangle);
}
}
public static void main (String args []) {
new ImageLabeller("/change to/a photo/ of your choice.jpg");
}
}
_
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel implements MouseListener,
MouseMotionListener {
Rectangle currentRectangle = null;
boolean drawingRectangle = false;
/**
* some java stuff to get rid of warnings
*/
private static final long serialVersionUID = 1L;
/**
* image to be tagged
*/
BufferedImage image = null;
/**
* list of current polygon's vertices
*/
ArrayList<Point> currentPolygon = null;
/**
* list of polygons
*/
ArrayList<ArrayList<Point>> polygonsList = null;
ArrayList<Rectangle> rectangleList = null;
/**
* extended constructor - loads image to be labelled
*
* #param imageName
* - path to image
* #throws Exception
* if error loading the image
*/
public ImagePanel(String imageName) throws Exception {
currentPolygon = new ArrayList<Point>();
polygonsList = new ArrayList<ArrayList<Point>>();
rectangleList = new ArrayList<Rectangle>();
image = ImageIO.read(new File(imageName));
Dimension panelSize = new Dimension(image.getWidth(), image.getHeight());
this.setSize(panelSize);
this.setMinimumSize(panelSize);
this.setPreferredSize(panelSize);
this.setMaximumSize(panelSize);
setBounds(0, 0, image.getWidth(), image.getHeight());
addMouseListener(this);
addMouseMotionListener(this);
this.setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Paint Component");
Graphics2D g2d = (Graphics2D) g;
// Paint image on screen
g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
// display all the completed polygons
for (ArrayList<Point> polygon : polygonsList) {
drawPolygon(polygon);
finishPolygon(polygon);
System.out.println("Polly");
}
// Display all completed squares
for (Rectangle r : rectangleList) {
drawRectangle(r);
System.out.println("Square");
}
// display current polygon
if (currentPolygon != null) {
drawPolygon(currentPolygon);
}
// display current square
if (currentRectangle != null) {
drawRectangle(currentRectangle);
}
}
/**
* displays a polygon without last stroke
*
* #param polygon
* to be displayed
*/
public void drawPolygon(ArrayList<Point> polygon) {
Graphics2D g = (Graphics2D) this.getGraphics();
// set to red so I can see when it's being redrawn
g.setColor(Color.RED);
g.setStroke(new BasicStroke(3));
for (int i = 0; i < polygon.size(); i++) {
Point currentVertex = polygon.get(i);
if (i != 0) {
Point prevVertex = polygon.get(i - 1);
g.drawLine(prevVertex.getX(), prevVertex.getY(),
currentVertex.getX(), currentVertex.getY());
}
g.fillOval(currentVertex.getX() - 5, currentVertex.getY() - 5, 10,
10);
}
}
public void drawRectangle(Rectangle r) {
Graphics2D g = (Graphics2D) this.getGraphics();
g.setStroke(new BasicStroke(3));
g.setColor(Color.BLUE);
g.drawLine(r.getX1(), r.getY1(), r.getX2(), r.getY1());
g.drawLine(r.getX1(), r.getY1(), r.getX1(), r.getY2());
g.drawLine(r.getX2(), r.getY2(), r.getX2(), r.getY1());
g.drawLine(r.getX2(), r.getY2(), r.getX1(), r.getY2());
System.out.println(r.getX1() + " " + r.getY1() + " " + r.getX2());
System.out.println("Drawn rectangle");
}
/**
* displays last stroke of the polygon (arch between the last and first
* vertices)
*
* #param polygon
* to be finished
*/
public void finishPolygon(ArrayList<Point> polygon) {
// if there are less than 3 vertices than nothing to be completed
if (polygon.size() >= 3) {
Point firstVertex = polygon.get(0);
Point lastVertex = polygon.get(polygon.size() - 1);
Graphics2D g = (Graphics2D) this.getGraphics();
g.setColor(Color.GREEN);
g.setStroke(new BasicStroke(3));
g.drawLine(firstVertex.getX(), firstVertex.getY(),
lastVertex.getX(), lastVertex.getY());
}
}
/**
* moves current polygon to the list of polygons and makes pace for a new
* one
*/
public void addNewPolygon() {
// finish the current polygon if any
if (currentPolygon != null) {
finishPolygon(currentPolygon);
polygonsList.add(currentPolygon);
}
currentPolygon = new ArrayList<Point>();
}
public void mouseClicked(MouseEvent e) {
if (!drawingRectangle) {
int x = e.getX();
int y = e.getY();
// check if the cursor is within image area
if (x > image.getWidth() || y > image.getHeight()) {
// if not do nothing
return;
}
Graphics2D g = (Graphics2D) this.getGraphics();
// if the left button than we will add a vertex to poly
if (e.getButton() == MouseEvent.BUTTON1) {
g.setColor(Color.GREEN);
if (currentPolygon.size() != 0) {
Point lastVertex = currentPolygon
.get(currentPolygon.size() - 1);
g.setStroke(new BasicStroke(3));
g.drawLine(lastVertex.getX(), lastVertex.getY(), x, y);
}
g.fillOval(x - 5, y - 5, 10, 10);
currentPolygon.add(new Point(x, y));
System.out.println(x + " " + y + " polygon point");
}
}
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
public void mousePressed(MouseEvent arg0) {
if (drawingRectangle) {
currentRectangle = new Rectangle(arg0.getX(), arg0.getY(),
arg0.getX(), arg0.getY(), Color.BLACK);
}
}
public void mouseReleased(MouseEvent arg0) {
if (drawingRectangle) {
rectangleList.add(new Rectangle(currentRectangle.getX1(),
currentRectangle.getY1(), arg0.getX(), arg0.getY(),
currentRectangle.getColor()));
System.out.println(currentRectangle.getX1() + " "
+ currentRectangle.getY1() + " " + arg0.getX() + " "
+ arg0.getY() + " rectangle point");
// unnecessary when mouseDragged calls paintComponent directly?
drawRectangle(new Rectangle(currentRectangle.getX1(),
currentRectangle.getY1(), arg0.getX(), arg0.getY(),
currentRectangle.getColor()));
currentRectangle = null;
drawingRectangle = false;
}
}
public void mouseDragged(MouseEvent arg0) {
if (drawingRectangle) {
currentRectangle = new Rectangle(currentRectangle.getX1(),
currentRectangle.getY1(), arg0.getX(), arg0.getY(),
currentRectangle.getColor());
System.out.println(currentRectangle.getX1() + " "
+ currentRectangle.getY1() + " " + arg0.getX() + " "
+ arg0.getX() + " " + "Dragging");
repaint();
// It works better using this instead on repaint()
// Graphics g = this.getGraphics();
// paintComponent(g);
}
}
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
-
public class Point {
private int x = 0;
private int y = 0;
public Point() {
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
-
import java.awt.Color;
import java.awt.Graphics2D;
public class Rectangle {
// Initialize variables
private int x1; // x coordinate of first endpoint
private int y1; // y coordinate of first endpoint
private int x2; // x coordinate of second endpoint
private int y2; // y coordinate of second endpoint
private Color colour; // colour of the shape
// A no-parameter constructor that sets all the coordinates of the shape to
// 0 and the
// colour to Color.BLACK
public Rectangle() {
x1 = 0;
y1 = 0;
x2 = 0;
y2 = 0;
colour = Color.BLACK;
}
// A constructor that initializes the coordinates and colour to the values
// of the
// parameters supplied.
public Rectangle(int x1, int y1, int x2, int y2, Color col) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.colour = col;
}
public void setX1(int x1) {
this.x1 = x1;
}
public void setY1(int y1) {
this.y1 = y1;
}
public void setX2(int x2) {
this.x2 = x2;
}
public void setY2(int y2) {
this.y2 = y2;
}
public void setColor(Color colour) {
this.colour = colour;
}
public int getX1() {
return this.x1;
}
public int getY1() {
return this.y1;
}
public int getX2() {
return this.x2;
}
public int getY2() {
return this.y2;
}
public Color getColor() {
return this.colour;
}
public int getWidth() {
return (Math.abs(x2 - x1));
}
public int getHeight() {
return (Math.abs(y2 - y1));
}
public int getUpperLeftX() {
return (Math.min(x1, x2));
}
public int getUpperLeftY() {
return (Math.min(y1, y2));
}
}
Sorry for the mass of code, I tried to trim out as much as I could.
Clicking on the image draws points which are joined up to create lines. When the user clicks the "New Object" button, the first and last points are joined to create a polygon. This all works fine, but if you click "New Square" and drag on the image, all previous shapes flicker as the mouse is moved and disappear when the mouse button is released. If "New Square" is clicked again (a necessity of poor coding on my behalf so far) and another square drawn, the 'disappeared' shapes can be seen flickering again, but then disappear once the mouse is released.
I'm calling repaint() in the mouseDragged(...) event, which I thought was all that was necessary. It actually works (almost) as wanted when I change
repaint();
for
Graphics g = this.getGraphics();
paintComponent(g);
but every book and article I've read said I should never call paintComponent myself, ever. An issue with calling paintComponent however is that the background image tends to flicker alot.
If repaint() calls paintComponent, why do they lead to different results?
I also don't understand why, when using repaint() in the mouseDragged event, I must , I must also call drawRectangle(...) in mouseReleased for the square to be seen at all, but when using paintComponent, I don't?
Any advice or pointers are greatly appreciated, thankyou.
In your drawRectangle and drawPolygon you are re-getting a graphics object, but you are calling them from paintComponent. this is what's causing the odd behaviour, you should pass the graphics from painComponent in to those methods.
I am seeing other odd behaviour though, like the polygons stay green until I've finished painting a square, when they then turn red, but one of the lines stays green and eventually vanishes. I didn't look in to that too much.
Also, polygon drawing and Point and Rectangle are supported in awt, is there any reason you chose to create your own classes for those?
package test;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel implements MouseListener,
MouseMotionListener {
Rectangle currentRectangle = null;
boolean drawingRectangle = false;
/**
* some java stuff to get rid of warnings
*/
private static final long serialVersionUID = 1L;
/**
* image to be tagged
*/
BufferedImage image = null;
/**
* list of current polygon's vertices
*/
ArrayList<Point> currentPolygon = null;
/**
* list of polygons
*/
ArrayList<ArrayList<Point>> polygonsList = null;
ArrayList<Rectangle> rectangleList = null;
/**
* extended constructor - loads image to be labelled
*
* #param imageName
* - path to image
* #throws Exception
* if error loading the image
*/
public ImagePanel(String imageName) throws Exception {
currentPolygon = new ArrayList<Point>();
polygonsList = new ArrayList<ArrayList<Point>>();
rectangleList = new ArrayList<Rectangle>();
image = ImageIO.read(new File(imageName));
Dimension panelSize = new Dimension(image.getWidth(), image.getHeight());
this.setSize(panelSize);
this.setMinimumSize(panelSize);
this.setPreferredSize(panelSize);
this.setMaximumSize(panelSize);
setBounds(0, 0, image.getWidth(), image.getHeight());
addMouseListener(this);
addMouseMotionListener(this);
this.setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Paint Component");
Graphics2D g2d = (Graphics2D) g;
// Paint image on screen
g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
// display all the completed polygons
for (ArrayList<Point> polygon : polygonsList) {
drawPolygon(polygon,g);
finishPolygon(polygon);
System.out.println("Polly");
}
// Display all completed squares
for (Rectangle r : rectangleList) {
drawRectangle(r,g);
System.out.println("Square");
}
// display current polygon
if (currentPolygon != null) {
drawPolygon(currentPolygon, g);
}
// display current square
if (currentRectangle != null) {
drawRectangle(currentRectangle, g);
}
}
/**
* displays a polygon without last stroke
*
* #param polygon
* to be displayed
*/
public void drawPolygon(ArrayList<Point> polygon, Graphics gr) {
Graphics2D g = null;
if (gr instanceof Graphics2D) {
g = (Graphics2D) gr;
}
else{ return; }
// set to red so I can see when it's being redrawn
g.setColor(Color.RED);
g.setStroke(new BasicStroke(3));
for (int i = 0; i < polygon.size(); i++) {
Point currentVertex = polygon.get(i);
if (i != 0) {
Point prevVertex = polygon.get(i - 1);
g.drawLine(prevVertex.getX(), prevVertex.getY(),
currentVertex.getX(), currentVertex.getY());
}
g.fillOval(currentVertex.getX() - 5, currentVertex.getY() - 5, 10,
10);
}
}
public void drawRectangle(Rectangle r, Graphics gr) {
Graphics2D g = null;
if (gr instanceof Graphics2D) {
g = (Graphics2D) gr;
}
else{ return; }
g.setStroke(new BasicStroke(3));
g.setColor(Color.BLUE);
g.drawLine(r.getX1(), r.getY1(), r.getX2(), r.getY1());
g.drawLine(r.getX1(), r.getY1(), r.getX1(), r.getY2());
g.drawLine(r.getX2(), r.getY2(), r.getX2(), r.getY1());
g.drawLine(r.getX2(), r.getY2(), r.getX1(), r.getY2());
System.out.println(r.getX1() + " " + r.getY1() + " " + r.getX2());
System.out.println("Drawn rectangle");
}
/**
* displays last stroke of the polygon (arch between the last and first
* vertices)
*
* #param polygon
* to be finished
*/
public void finishPolygon(ArrayList<Point> polygon) {
// if there are less than 3 vertices than nothing to be completed
if (polygon.size() >= 3) {
Point firstVertex = polygon.get(0);
Point lastVertex = polygon.get(polygon.size() - 1);
Graphics2D g = (Graphics2D) this.getGraphics();
g.setColor(Color.GREEN);
g.setStroke(new BasicStroke(3));
g.drawLine(firstVertex.getX(), firstVertex.getY(),
lastVertex.getX(), lastVertex.getY());
}
}
/**
* moves current polygon to the list of polygons and makes pace for a new
* one
*/
public void addNewPolygon() {
// finish the current polygon if any
if (currentPolygon != null) {
finishPolygon(currentPolygon);
polygonsList.add(currentPolygon);
}
currentPolygon = new ArrayList<Point>();
}
public void mouseClicked(MouseEvent e) {
if (!drawingRectangle) {
int x = e.getX();
int y = e.getY();
// check if the cursor is within image area
if (x > image.getWidth() || y > image.getHeight()) {
// if not do nothing
return;
}
Graphics2D g = (Graphics2D) this.getGraphics();
// if the left button than we will add a vertex to poly
if (e.getButton() == MouseEvent.BUTTON1) {
g.setColor(Color.GREEN);
if (currentPolygon.size() != 0) {
Point lastVertex = currentPolygon
.get(currentPolygon.size() - 1);
g.setStroke(new BasicStroke(3));
g.drawLine(lastVertex.getX(), lastVertex.getY(), x, y);
}
g.fillOval(x - 5, y - 5, 10, 10);
currentPolygon.add(new Point(x, y));
System.out.println(x + " " + y + " polygon point");
}
}
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
public void mousePressed(MouseEvent arg0) {
if (drawingRectangle) {
currentRectangle = new Rectangle(arg0.getX(), arg0.getY(),
arg0.getX(), arg0.getY(), Color.BLACK);
}
}
public void mouseReleased(MouseEvent arg0) {
if (drawingRectangle) {
rectangleList.add(new Rectangle(currentRectangle.getX1(),
currentRectangle.getY1(), arg0.getX(), arg0.getY(),
currentRectangle.getColor()));
System.out.println(currentRectangle.getX1() + " "
+ currentRectangle.getY1() + " " + arg0.getX() + " "
+ arg0.getY() + " rectangle point");
// unnecessary when mouseDragged calls paintComponent directly?
/*drawRectangle(new Rectangle(currentRectangle.getX1(),
currentRectangle.getY1(), arg0.getX(), arg0.getY(),
currentRectangle.getColor()));*/
currentRectangle = null;
drawingRectangle = false;
}
}
public void mouseDragged(MouseEvent arg0) {
if (drawingRectangle) {
currentRectangle = new Rectangle(currentRectangle.getX1(),
currentRectangle.getY1(), arg0.getX(), arg0.getY(),
currentRectangle.getColor());
System.out.println(currentRectangle.getX1() + " "
+ currentRectangle.getY1() + " " + arg0.getX() + " "
+ arg0.getX() + " " + "Dragging");
repaint();
// It works better using this instead on repaint()
// Graphics g = this.getGraphics();
// paintComponent(g);
}
}
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}

Categories