How can I prevent shapes from changing on mouseclick? - java

I am having a problem with my code, if I click on rectangle and do the mouse clicks on the screen it will show the shape and it works fine.. but if I clicked on the circle after that, all the rec
tangles that have been stored stays on same location but changes to circle. how can I prevent the shapes that have been stored from changing?
First Class:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class MouseClick implements ActionListener{
private static int x,y;
private static DrawingObjects object = new DrawingObjects();
JPanel panel = new JPanel();
JFrame frame = new JFrame("MouseClick");
MouseClick(){
dObjects();
}
void dObjects() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(2,2));
frame.add(object);
frame.add(panel);
panel.setBackground(Color.WHITE);
panel.setSize(10, 300);
panel.setLocation(100, 200);
panel.setLayout(new GridLayout(1,2));
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setSize(400, 400);
object.addMouseListener(new AL());
Button rect = new Button("Rectangle");
Button oval = new Button("Circle");
panel.add(rect);
panel.add(oval);
rect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
object.setType(1);
}
});
oval.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
object.setType(2);
}
}); }
public static void main(String[] args){
new MouseClick();
}
static class AL extends MouseAdapter{
public void mouseClicked (MouseEvent e){
x = e.getX();
y = e.getY();
object.drawing(x, y);
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
Second Class:
import javax.swing.*;
import javafx.scene.input.MouseEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.*;
public class DrawingObjects extends JPanel{
private ArrayList<Point> points = new ArrayList<>();
public int shapetype ;
public void drawing(int x, int y){
points.add(new Point(x, y));
repaint();
}
public void setType(int choice){
if(choice==1){
shapetype = 1;
}
else if (choice ==2){
shapetype = 2;
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
if(shapetype == 1){
for(Point p : points){
g.fillRect(p.x, p.y, 60, 20);
g.setColor(Color.GREEN);
repaint();
}
}
else if (shapetype == 2){
for(Point p : points){
g.fillOval(p.x, p.y, 20, 20);
g.setColor(Color.RED);
repaint();
}
}
}
}

The problem occurs because the shapetype is not stored along with the points on which the shapes are drawn. As a result, within the paintComponent method, when all shapes in locations stored in points array get redrawn, they use the current value of shapetype. Not the value of shapetype when the shape was created for the first time.
A simple (yet not the best) solution, with minimum code change would be to store the shapetype as follows.
In DrawingObjects class, add another array to store the shapetype.
private ArrayList<Integer> shapeTypes = new ArrayList<>();
Update the drawing method as follows to store the current shapetype along with the point.
public void drawing(int x, int y) {
points.add(new Point(x, y));
shapeTypes.add(shapetype);
repaint();
}
Refer the stored shapetype when repainting the shapes as follows.
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < points.size(); i++) {
Point p = points.get(i);
if (shapeTypes.get(i) == 1) {
g.fillRect(p.x, p.y, 60, 20);
g.setColor(Color.GREEN);
repaint();
} else if (shapeTypes.get(i) == 2) {
g.fillOval(p.x, p.y, 20, 20);
g.setColor(Color.RED);
repaint();
}
}
}
A better design would be to create a separate class with the capability to store the location as well as the shape type with the implementation on how it should be painted.

Related

How to make ball drawn with Java bounce off the edges of the panel?

I have java code that draws a red ball inside a class that extends the JPanel class, I have a timer that is enabled by a button that updates the position of the ball with timer ctor variable elapse. I am trying to get the difference of the height of the panel and the YPOSITION where the circle is drawn if its less than 0 the the bounce ball needs to keep moving down else it should move up, my ball hits the wall and keeps hitting it. Help me debug the code that is causing that to happen.
RightPanel class
import javax.swing.*;
import java.awt.*;
public class RightPanel extends JPanel {
//define the position where the circle will be drawn
private int positionX=150;
private int positionY=150;
private int radius=100;//as the shape is a circle
//override the paint method to draw the bounce ball on the second panel
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d= (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.RED);
g2d.fillOval(positionX,positionY,radius,radius);
}
//let's us update the position of the ball from another class
public int getPositionY(){
public void setPositionX(int positionX) {
this.positionX = positionX;
}
public void setPositionY(int positionY){
this.positionY=positionY;
}
public int getPositionX(){
return this.positionX;
}
return this.positionY;
}
}
The logic in the timer class below is the one I need help with
GameInterface class
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class GameInterface extends JFrame {
//declare a Timer object to start the movement
Graphics ctx;
RightPanel rightpanel;
private int height;
//declare a timer to start moving the ball
Timer mytimer= new Timer(50, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
//check this and keep moving the ball down
if(rightpanel.getPositionY()- rightpanel.getHeight()<0){
rightpanel.setPositionY(rightpanel.getPositionY()+5);
rightpanel.paint(rightpanel.getGraphics());
}else{
//move the ball up
rightpanel.setPositionY(rightpanel.getPositionY()-5);
rightpanel.paint(rightpanel.getGraphics());
}
}
});
public GameInterface(){
setSize(new Dimension(800, 600));
height=this.getHeight();
setResizable(false);
setTitle("Bounce Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.black);
//define a new JSplitPane and use it to add two JPanels
JPanel leftpanel= new JPanel();
//add buttons to the left panel programatically
JButton up= new JButton("Move up");
//set the event listeners for the buttons
up.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
//start he timer
mytimer.start();
}
});
JButton down = new JButton("Move down");
down.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
//move my ball down
rightpanel.setPositionX(rightpanel.getPositionX());
rightpanel.setPositionY(rightpanel.getPositionY()+5);
rightpanel.paint(rightpanel.getGraphics());
}
});
leftpanel.add(up);
leftpanel.add(down);
rightpanel= new RightPanel();
JSplitPane splitpane= new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftpanel,rightpanel);
this.add(splitpane);
setVisible(true);
ctx=this.getGraphics();
}
}
The basic idea is, when you "drop" the ball, you need to determine the direction of movement that the ball should move in. When the timer ticks, it will apply that direction of movement until it either reaches the bottom, at which time the delta is reversed, or it reaches the top.
The important part here is, all the state the timer needs should be determined before the timer is started and not calculated within the timer itself, as the state it needs is no longer relevant.
For example...
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.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Ball ball = new Ball(20);
JFrame frame = new JFrame();
frame.add(new MainPane(ball));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Ball {
private Point location;
private Dimension size;
private Shape shape;
public Ball(int radius) {
location = new Point(0, 0);
size = new Dimension(radius * 2, radius * 2);
shape = new Ellipse2D.Double(0, 0, radius * 2, radius * 2);
}
public Rectangle getBounds() {
return new Rectangle(location, size);
}
public void setLocation(Point p) {
location = new Point(p);
}
public void paint(Graphics2D g2d) {
g2d = (Graphics2D) g2d.create();
g2d.setColor(Color.RED);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate(location.x, location.y);
g2d.fill(shape);
g2d.dispose();
}
}
public class SurfacePane extends JPanel {
private Ball ball;
private Timer timer;
private int yDelta;
public SurfacePane(Ball ball) {
this.ball = ball;
this.ball.setLocation(new Point(200 - (ball.getBounds().width / 2), 0));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
ball.paint(g2d);
g2d.dispose();
}
public void moveBallDown() {
Rectangle bounds = ball.getBounds();
Dimension size = ball.size;
Point location = bounds.getLocation();
location.y += size.height;
if (location.y + size.height > getHeight()) {
location.y = getHeight() - size.height;
}
ball.setLocation(location);
repaint();
}
public void dropBall() {
if (timer != null) {
return;
}
Rectangle bounds = ball.getBounds();
Dimension size = ball.size;
Point location = bounds.getLocation();
if (location.y + size.height > getHeight()) {
yDelta = -1;
} else {
yDelta = 1;
}
timer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Rectangle bounds = ball.getBounds();
Dimension size = ball.size;
Point location = bounds.getLocation();
location.y += yDelta;
if (location.y < 0) {
location.y = 0;
yDelta = 0;
timer.stop();
timer = null;
} else if (location.y + size.height > getHeight()) {
location.y = getHeight() - size.height;
yDelta *= -1;
}
ball.setLocation(location);
repaint();
}
});
timer.start();
}
}
public class MainPane extends JPanel {
private Ball ball;
private SurfacePane surfacePane;
public MainPane(Ball ball) {
setLayout(new BorderLayout());
this.ball = ball;
surfacePane = new SurfacePane(ball);
add(surfacePane);
JPanel actionPane = new JPanel(new GridBagLayout());
JButton up = new JButton("Up");
JButton down = new JButton("Down");
actionPane.add(up);
actionPane.add(down);
add(actionPane, BorderLayout.SOUTH);
up.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
surfacePane.dropBall();
}
});
down.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
surfacePane.moveBallDown();
}
});
}
}
}

How to draw a continuous curve of repeated ovals on speedy mouse cursor dragging?

This code is for drawing on a JPanel. In the paintComponent(Graphics) I am trying to draw curves via repeated Graphics2D#fillOval(x, y, with, height).
The app is working OK, and when I drag the mouse cursor slowly; it draws a continuous curve as I need. But when I speed up dragging the mouse cursor, the result is separated dots and not a continuous curve.
So how to make it draw a continuous curve even if I speed up dragging?
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class Painter extends JPanel {
int x, y;
ArrayList<Point> points;
public Painter() {
setBackground(Color.white);
points = new ArrayList<>();
MouseHandler listener = new MouseHandler();
this.addMouseMotionListener(listener);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
private class MouseHandler extends MouseAdapter implements MouseMotionListener {
#Override
public void mouseDragged(MouseEvent e) {
Point point = new Point(e.getX(), e.getY());
points.add(point);
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Point point : points) {
g2d.fillOval(point.x, point.y, 15, 15);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
f.setContentPane(new Painter());
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}
As mentioned in comment to your previous similar question:
Don't draw discrete ovals in your paintComponent method.
Instead connect the points hold in the List in the paintComponent by drawing lines between adjacent points.
If you need to make the line thicker, change the Stroke property of the Graphics2D object, using one that has a wider thickness.
Be careful with Strokes however since often you don't want the property change to propagate down the paint chain. This means that sometimes you will want to copy the Graphics object and set the Stroke on the new Graphics object and paint with that, then dispose of it.
The simplest way to create a Stroke is to use the BasicStroke class, e.g., new BasicStroke(6f) will get you a nice thick curve.
For example:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class Painter2 extends JPanel {
private static final float STROKE_WIDTH = 15f;
private static final Stroke STROKE = new BasicStroke(STROKE_WIDTH, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
int x, y;
ArrayList<Point> points;
public Painter2() {
setBackground(Color.white);
points = new ArrayList<>();
MouseHandler listener = new MouseHandler();
this.addMouseMotionListener(listener);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
private class MouseHandler extends MouseAdapter implements MouseMotionListener {
#Override
public void mouseDragged(MouseEvent e) {
Point point = new Point(e.getX(), e.getY());
points.add(point);
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(STROKE);
for (int i = 1; i < points.size(); i++) {
int x1 = points.get(i - 1).x;
int y1 = points.get(i - 1).y;
int x2 = points.get(i).x;
int y2 = points.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
f.setContentPane(new Painter2());
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}
Or better still:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class Painter2 extends JPanel {
private static final float STROKE_WIDTH = 15f;
private static final Stroke STROKE = new BasicStroke(STROKE_WIDTH, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND);
private static final Color CURVES_COLOR = Color.BLUE;
private static final Color TEMP_CURVE_COLOR = Color.PINK;
private List<List<Point>> curvesList = new ArrayList<>();
private List<Point> tempCurve = null;
public Painter2() {
setBackground(Color.white);
MouseHandler listener = new MouseHandler();
addMouseListener(listener);
addMouseMotionListener(listener);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
private class MouseHandler extends MouseAdapter implements MouseMotionListener {
#Override
public void mousePressed(MouseEvent e) {
tempCurve = new ArrayList<>();
tempCurve.add(e.getPoint());
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
tempCurve.add(e.getPoint());
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
tempCurve.add(e.getPoint());
curvesList.add(tempCurve);
tempCurve = null;
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setStroke(STROKE);
g2.setColor(CURVES_COLOR);
for (List<Point> curve : curvesList) {
drawCurve(g2, curve);
}
if (tempCurve != null) {
g2.setColor(TEMP_CURVE_COLOR);
drawCurve(g2, tempCurve);
}
g2.dispose();
}
private void drawCurve(Graphics2D g2, List<Point> ptList) {
for (int i = 1; i < ptList.size(); i++) {
int x1 = ptList.get(i - 1).x;
int y1 = ptList.get(i - 1).y;
int x2 = ptList.get(i).x;
int y2 = ptList.get(i).y;
g2.drawLine(x1, y1, x2, y2);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
f.setContentPane(new Painter2());
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}

Java Array Loop Graphics page not functioning

edit 2: I decided that it would be easier to understand if I just put the entire code up, so that you can test it.
edit: I realize that what I said was unclear, so I will explain this as best as I can. Basically, I am drawing rectangles on a Graphics page using the fillRect method. The problem is that when I change the size of one, they all change, as they are all being redrawn everytime a new one is drawn. To correct this, I added an array that stores all of the sizes which are input via the scrollwheel in another part of the problem. Anyways, I know that the problem is isolated to the loop that supposedly draws them all a certain size, so I added a loop that in theory should give me a temporary variable each time to use that redraws all of the rectangle's sizes starting at 0 each time the main loop is run. The problem is that this does not in fact redraw the rectangles to their individual sizes, and instead draws them to the current size. I have updated the code part as well.
I am having trouble with a project in Java. What it is supposed to do is change the size of each individual rectangle object by storing it in an array, and then recreating the rectangles based off the length from the array. I (at least I think) do this by creating a variable that should be equal to the SIZE that is changed in another part of the program, and then set that equal to the particular element in the array at i. Anyhow, when I do this, I change all of the lengths to whatever the current length is when I draw a rectangle. I know that the problem is by me using i in the size part, but what would I use? Thanks in advance for any help!
Here is the code:
public class Dots
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Array Rectangles");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DotsPanel dotsPanel = new DotsPanel();
frame.getContentPane().add(dotsPanel);
//buttons
JButton btnNewButton = new JButton("RED");
btnNewButton.setHorizontalAlignment(SwingConstants.LEFT);
btnNewButton.setVerticalAlignment(SwingConstants.BOTTOM);
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
btnNewButton.setForeground(Color.RED);
dotsPanel.add(btnNewButton);
JButton btnNewButton_1 = new JButton("GREEN");
btnNewButton_1.setForeground(Color.GREEN);
btnNewButton_1.setVerticalAlignment(SwingConstants.BOTTOM);
dotsPanel.add(btnNewButton_1);
JButton btnNewButton_2 = new JButton("BLUE");
btnNewButton_2.setForeground(Color.BLUE);
dotsPanel.add(btnNewButton_2);
JButton btnNewButton_3 = new JButton("BLACK");
btnNewButton_3.setForeground(new Color(0, 0, 0));
dotsPanel.add(btnNewButton_3);
frame.pack();
frame.setVisible(true);
}
}
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
public class DotsPanel extends JPanel
{
// radius of each dot
private int SIZE = 25;
private int SIZEAccess;
private static final Random generator = new Random();
//used to count amount of dots
private ArrayList<Point> pointList;
int[] sizes = new int [10000];
//Sets up this std. sized panel to listen for mouse events.
public DotsPanel()
{
pointList = new ArrayList<Point>();
addMouseListener (new DotsListener());
addMouseMotionListener(new DotsListener());
addMouseWheelListener(new DotsListener());
setBackground(Color.white);
setPreferredSize(new Dimension(1024, 768));
}
//used to generate a random color
public static Color randomColor() {
return new Color(generator.nextInt(256), generator.nextInt(256), generator.nextInt(256));
}
// Draws all of the dots stored in the list.
public void paintComponent(Graphics page)
{
super.paintComponent(page);
//draws a centered dot of random color
int i = 0;
for (Point spot : pointList)
{
sizes[i] = SIZE;
//SIZEAccess = SIZE;
//sizes[i] = SIZEAccess;
//page.fillRect(spot.x-SIZE, spot.y-SIZE, SIZE*2, SIZE*2);
for (int temp = 0; temp <= i; temp++)
page.fillRect(spot.x-sizes[temp], spot.y-sizes[temp], sizes[temp]*2, sizes[temp]*2);
//page.fillRect(spot.x-SIZE, spot.y-SIZE, SIZE*2, SIZE*2);
//page.setColor(randomColor());
//page.setColor(c)
i++;
}
//displays the amount of rectangles drawn at the top left of screen
page.drawString("Count: " + pointList.size(), 5, 15);
page.drawString("To change the size of the squares, use mouse scroll wheel.", 350, 15);
page.drawString("Size: " + SIZE, 950, 15);
}
// Represents the listener for mouse events.
private class DotsListener implements MouseListener, MouseMotionListener, MouseWheelListener
{
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is pressed.
public void mousePressed(MouseEvent event)
{
pointList.add(event.getPoint());
repaint();
}
// Provide empty definitions for unused event methods.
public void mouseClicked(MouseEvent event) {
}
public void mouseReleased(MouseEvent event) {
}
public void mouseEntered(MouseEvent event) {
}
public void mouseExited(MouseEvent event) {}
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is dragged.
public void mouseDragged(MouseEvent event) {
pointList.add(event.getPoint());
repaint();
}
public void mouseMoved(MouseEvent event) {
}
public void mouseWheelMoved(MouseWheelEvent event)
{
int notches = 0;
notches = event.getWheelRotation();
//int
if (notches > 0)
{
SIZE = SIZE + notches;
notches = 0;
}
else if (notches < 0)
{
int tempSIZE = SIZE;
tempSIZE = tempSIZE + notches;
//prevents the program from having dots that increase due to multiplying negatives by negatives
//by making anything less than 1 equal 1
if(tempSIZE < 1)
tempSIZE = 1;
SIZE = tempSIZE;
notches = 0;
}
}
}
//SIZE = SIZE + notches;
}
You appear to have ArrayList's interacting with arrays in a confusing mix that makes it hard for us to follow your logic. This suggests that your logic may be too complex for your own good and that your code might benefit from simplification. Why not instead create a List<Rectangle> such as an ArrayList<Rectangle>, and then simply loop through this list in your paintComponent method, and draw each Rectangle using the Graphics2D object's draw(...) or fill(...) method:
private List<Rectangle> rectangleList = new ArrayList<>();
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle rectangle : rectangleList) {
g2.fill(rectangle);
}
}
For example:
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.Rectangle;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class Foo extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final Color BACKGROUND = Color.black;
private static final Color FILL_COLOR = Color.pink;
private static final Color DRAW_COLOR = Color.red;
private static final Stroke STROKE = new BasicStroke(3);
private List<Rectangle> rectangleList = new ArrayList<>();
private Point pressPoint = null;
private Point dragPoint = null;
public Foo() {
setBackground(BACKGROUND);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Stroke oldStroke = g2.getStroke();
g2.setStroke(STROKE);
for (Rectangle rectangle : rectangleList) {
g2.setColor(FILL_COLOR);
g2.fill(rectangle);
g2.setColor(DRAW_COLOR);
g2.draw(rectangle);
}
g2.setStroke(oldStroke);
if (pressPoint != null && dragPoint != null) {
g2.setColor(FILL_COLOR.darker());
int x = Math.min(pressPoint.x, dragPoint.x);
int y = Math.min(pressPoint.y, dragPoint.y);
int width = Math.abs(pressPoint.x - dragPoint.x);
int height = Math.abs(pressPoint.y - dragPoint.y);
g2.drawRect(x, y, width, height);
}
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
pressPoint = e.getPoint();
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
dragPoint = e.getPoint();
int x = Math.min(pressPoint.x, dragPoint.x);
int y = Math.min(pressPoint.y, dragPoint.y);
int width = Math.abs(pressPoint.x - dragPoint.x);
int height = Math.abs(pressPoint.y - dragPoint.y);
Rectangle rect = new Rectangle(x, y, width, height);
rectangleList.add(rect);
pressPoint = null;
dragPoint = null;
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Foo());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Using listeners and mouse pointer location to check if pointer is inside of a circle

I'm trying to make it so a line of text is drawn on the point of the cursor that states if the cursor is inside or outside of the drawn circle. I'm not entirely sure how to do that and I don't think that the global X and Y coordinates I've made are working properly.
Does anyone know of a way to some how trigger the string to be drawn when the cursor is in or out of the circle? I'm still sort of new to Java.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MouseCircleLocation extends JPanel {
boolean insideCircleStatus;
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int x = (int) b.getX();
int y = (int) b.getY();
public MouseCircleLocation() {
//the listener that checks if the mouse if moving.
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
//gets the location of the mouse.
int x = e.getX();
int y = e.getY();
//simple check to see if the mouse location is inside the circle area.
if ( (Math.pow((x - 100), 2)) + (Math.pow((y - 60), 2)) < (Math.pow((50), 2))){
insideCircleStatus = true;
}
else{
insideCircleStatus = false;
}
}
});
}
//basic frame setup.
public static void main(String[] args) {
JFrame frame = new JFrame("Mouse Location");
frame.add(new MouseCircleLocation());
frame.setSize(210, 190);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
//draws the circle.
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (insideCircleStatus = true){
g.drawString("Point is inside the circle", x, y);
System.out.println("Point is inside the circle");
}
if (insideCircleStatus = false){
g.drawString("Point is outside the circle", x, y);
System.out.println("Point is outside the circle");
}
g.setColor(Color.BLACK);
g.drawOval(100 - 50, 60 - 50, 50 *2, 50 * 2);
}
}
One thing you're forgetting to do is call repaint(). Just because the value of insideCircleStatus changes, doesn't make it automatically repaint(), so you'll want to call repaint() inside the MouseListener
Also, you could use the Shape interface and the method contains for example
Ellipse2D.Double circle = new Ellipse2D.Double(50, 50, 200, 200);
...
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e) {
if (circle.contains(e.getPoint())) {
System.out.println("Click within Circle");
}
}
});
See full example using MouseMotionListener and the API - Also See Ellips2D
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestShapeContains extends JPanel {
private static final int D_W = 500;
private static final int D_H = 500;
Ellipse2D.Double circle = new Ellipse2D.Double(50, 50, 300, 300);
Point p = new Point();
private boolean insideCircle = false;
public TestShapeContains() {
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseMoved(MouseEvent e) {
if (circle.contains(e.getPoint())) {
insideCircle = true;
} else {
insideCircle = false;
}
p = e.getPoint();
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.draw(circle);
if (insideCircle) {
g.drawString("Mouse in Circle at point " + (int)p.getX() + ", " + (int)p.getY(),
(int)p.getX(), (int)p.getY());
} else {
g.drawString("Mouse outside Circle at point " + (int)p.getX() + ", " + (int)p.getY(),
(int)p.getX(), (int)p.getY());
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_W, D_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new TestShapeContains());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

Moving objects and timers

I have a screen with say 500 width and 400 height, and I have a vector with a bunch of shapes. let say the vector has 2 different shapes for example. I want the object to randomly pop up from the bottom of the screen reach a certain ascent and then fall back down (similar to game fruit ninja, where the fruits are my shapes).
In my main (view) I have a vector of shapes of which i instantiate the timers, add to array and place them in the buttom of the screen using the translate function. My timer takes in an action listener which basically changes the translate of the shape to move up till ascent and then down, but my problem is that all the shapes start at the same time regardless.
Something like this:
Shape f = new Shape(new Area(new Ellipse2D.Double(0, 50, 50, 50)));
f.translate(0, 400);
f.timer = new Timer( 10 , taskPerformer);
f.timer.start();
vector.add(f);
Shape f2 = new Shape(new Area(new Rectangle2D.Double(0, 50, 50, 50)));
f2.translate(200, 400);
f2.timer = new Timer( 10 , taskPerformer);
f2.timer.setInitialDelay(5000);
f2.timer.start();
vector.add(f2);
and my action listener:
Random generator = new Random();
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
for (Shape s : model.getShapes()) {
// Scale object using translate
// once reached ascent drop down
// translate to diffrenet part of the bottom of the screen
// delay its timer
}
update();
//basically repaints
}
};
I'm running into problems that all shapes follow the same timer, and begin to pop up at the same time (no delay) ...
Any suggestions on how to avoid this or if there is a different approach i should try
"I want the object to randomly pop up from the bottom of the screen reach a certain ascent and then fall back down"
See the runnable example below. What I do is pass a radomDelayedStart to the Shape. Every tick of the timer, the randomDelayedStart decreases til it reaches 0, that's when the flag to be drawn in raised. Most of the logic is in the Shape class methods, which are called in the Timers Actionlistener. Everything is done in one Timer. For the ascent, I just used a hard coded 50, but you can also pass a random ascent to the Shape. Let me know if you have any questions. I tried to made the code as clear as possible.
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.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class RandomShape extends JPanel {
private static final int D_HEIGHT = 500;
private static final int D_WIDTH = 400;
private static final int INCREMENT = 8;
private List<Shape> shapes;
private List<Color> colors;
private Timer timer = null;
public RandomShape() {
colors = createColorList();
shapes = createShapeList();
timer = new Timer(30, new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (Shape shape : shapes) {
shape.move();
shape.decreaseDelay();
repaint();
}
}
});
JButton start = new JButton("Start");
start.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
JButton reset = new JButton("Reset");
reset.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
shapes = createShapeList();
timer.restart();
}
});
JPanel panel = new JPanel();
panel.add(start);
panel.add(reset);
setLayout(new BorderLayout());
add(panel, BorderLayout.PAGE_START);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Shape shape : shapes) {
shape.drawShape(g);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_WIDTH, D_HEIGHT);
}
private List<Color> createColorList() {
List<Color> list = new ArrayList<>();
list.add(Color.BLUE);
list.add(Color.GREEN);
list.add(Color.ORANGE);
list.add(Color.MAGENTA);
list.add(Color.CYAN);
list.add(Color.PINK);
return list;
}
private List<Shape> createShapeList() {
List<Shape> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
int randXLoc = random.nextInt(D_WIDTH);
int randomDelayedStart = random.nextInt(100);
int colorIndex = random.nextInt(colors.size());
Color color = colors.get(colorIndex);
list.add(new Shape(randXLoc, randomDelayedStart, color));
}
return list;
}
class Shape {
int randXLoc;
int y = D_HEIGHT;
int randomDelayedStart;
boolean draw = false;
boolean down = false;
Color color;
public Shape(int randXLoc, int randomDelayedStart, Color color) {
this.randXLoc = randXLoc;
this.randomDelayedStart = randomDelayedStart;
this.color = color;
}
public void drawShape(Graphics g) {
if (draw) {
g.setColor(color);
g.fillOval(randXLoc, y, 30, 30);
}
}
public void move() {
if (draw) {
if (y <= 50) {
down = true;
}
if (down) {
y += INCREMENT;
} else {
y -= INCREMENT;
}
}
}
public void decreaseDelay() {
if (randomDelayedStart <= 0) {
draw = true;
} else {
randomDelayedStart -= 1;
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new RandomShape());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

Categories

Resources