Why is my method not clearing the ArrayList? - java

NOTE: The problem with my code was simply that I created the method to clear the rects and everything but the only thing I was doing wrong was instantiating DrawPanel class's myDraw object inside of the go() method. And so I had to instantiate DrawPanel again with Stop and that created a whole new object. So I ended up calling the clearRects method on a different DrawPanel object than the one rects were being added to. Anyway, I decided to go with code suggestions by MadProgrammer because his code was exactly how Java: A Beginner's Guide teaches it and was much cleaner.
Well, I have been running around StackOverflow since this morning and have been able to fix a lot of problems with my code but I am still stuck with this problem with ArrayLists.
I have the following piece of code that does not seem to do what I intend for it to do. Now I am aware that I am the one making a mistake somewhere but not really sure how to correct it.
The way it is set up is that when I hit the stop button, the ArrayList should clear so I have a blank JPanel so to speak, here's the code snippets. I can post the whole program if you want me to though but I am only pasting the snippet here because I'm assuming I'm making a pretty simple and dumb mistake on my part:
class DrawPanel extends JPanel {
ArrayList<MyRectangle> rects = new ArrayList<>();
Random rand = new Random();
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
addRect();
for(MyRectangle r : rects) {
g.setColor(r.getColor());
g.fillRect(r.x, r.y, r.width, r.height);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500,500);
}
public ArrayList<MyRectangle> addRect() {
int ht = rand.nextInt(getHeight());
int wd = rand.nextInt(getWidth());
int x = rand.nextInt(getWidth() - wd);
int y = rand.nextInt(getHeight() - ht);
int r = rand.nextInt(256);
int g = rand.nextInt(256);
int b = rand.nextInt(256);
rects.add(new MyRectangle(x, y, wd, ht, new Color(r, b, g)));
System.out.println(rects.size());
return rects;
}
public void clearEvent(ActionEvent e) {
System.out.println(rects.size());
rects.clear();
frame.repaint();
System.out.println("I was called");
}
}
And here's the part where the button calls it in its actionPerformed method:
class StopListener implements ActionListener {
DrawPanel draw = new DrawPanel();
public void actionPerformed(ActionEvent e) {
timer.stop();
draw.clearEvent(e);
}
}
EDIT: I understand that the arraylist object that my clearEvent method refers to is not the same one that addRect()'s adding stuff to. What I am asking, I guess, is how to make it "connect" so I can wipe things clean using the JButton.
EDIT: Here's the full program:
import javax.swing.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Random;
import java.awt.*;
public class TwoButtonsRandomRec {
JFrame frame;
Timer timer;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TwoButtonsRandomRec test = new TwoButtonsRandomRec();
test.go();
}
});
}
public void go() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton startButton = new JButton("Start");
startButton.addActionListener(new StartListener());
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(new StopListener());
final DrawPanel myDraw = new DrawPanel();
timer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
myDraw.repaint();
}
});
frame.add(startButton, BorderLayout.NORTH);
frame.add(stopButton, BorderLayout.SOUTH);
frame.add(myDraw, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
class StartListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
timer.start();
}
}
class StopListener implements ActionListener {
DrawPanel draw = new DrawPanel();
public void actionPerformed(ActionEvent e) {
timer.stop();
draw.clearEvent(e);
}
}
class DrawPanel extends JPanel {
ArrayList<MyRectangle> rects = new ArrayList<>();
Random rand = new Random();
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
addRect();
for(MyRectangle r : rects) {
g.setColor(r.getColor());
g.fillRect(r.x, r.y, r.width, r.height);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500,500);
}
public ArrayList<MyRectangle> addRect() {
int ht = rand.nextInt(getHeight());
int wd = rand.nextInt(getWidth());
int x = rand.nextInt(getWidth() - wd);
int y = rand.nextInt(getHeight() - ht);
int r = rand.nextInt(256);
int g = rand.nextInt(256);
int b = rand.nextInt(256);
rects.add(new MyRectangle(x, y, wd, ht, new Color(r, b, g)));
System.out.println(rects.size());
return rects;
}
public void clearEvent(ActionEvent e) {
System.out.println(rects.size());
rects.clear();
repaint();
System.out.println("I was called");
}
}
}
class MyRectangle extends Rectangle {
Color color;
public MyRectangle(int x, int y, int w, int h, Color c) {
super(x, y, w, h);
this.color = c;
}
public Color getColor() {
return color;
}
}
Here's the previous relevant question I asked here in case anyone's interested.
Strange JFrame Behavior

I see two immediate issues.
The first is, you're calling addRect within the paintComponent method, which means, even after you clear the List, on the next repaint, a new rectangle will be added to it.
Secondly, I would call repaint in the DrawPanel instead of using frame.repaint(), as you really only want to update the draw panel, not the entire frame
public class BadPaint05 {
public static void main(String[] args) {
new BadPaint05();
}
public BadPaint05() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new MasterPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MasterPane extends JPanel {
private DrawPanel drawPane;
private Timer timer;
public MasterPane() {
setLayout(new BorderLayout());
drawPane = new DrawPanel();
add(drawPane);
JButton stop = new JButton("Stop");
stop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
drawPane.clearEvent(e);
timer.stop();
}
});
timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
drawPane.addRect();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
add(stop, BorderLayout.SOUTH);
}
}
class DrawPanel extends JPanel {
ArrayList<MyRectangle> rects = new ArrayList<>();
Random rand = new Random();
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// addRect();
for (MyRectangle r : rects) {
g.setColor(r.getColor());
g.fillRect(r.x, r.y, r.width, r.height);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public ArrayList<MyRectangle> addRect() {
int ht = rand.nextInt(getHeight());
int wd = rand.nextInt(getWidth());
int x = rand.nextInt(getWidth() - wd);
int y = rand.nextInt(getHeight() - ht);
int r = rand.nextInt(256);
int g = rand.nextInt(256);
int b = rand.nextInt(256);
rects.add(new MyRectangle(x, y, wd, ht, new Color(r, b, g)));
System.out.println(rects.size());
repaint();
return rects;
}
public void clearEvent(ActionEvent e) {
System.out.println(rects.size());
rects.clear();
// frame.repaint();
repaint();
System.out.println("I was called");
}
}
public class MyRectangle {
private int x, y, width, height;
private Color color;
private MyRectangle(int x, int y, int wd, int ht, Color color) {
this.x = x;
this.y = y;
this.width = wd;
this.height = ht;
this.color = color;
}
public Color getColor() {
return color;
}
}
}

Related

can't draw on a JPanel after repaint method

I'm experimenting on a GUI that I programmed and I don't understand how I can fix my problem:
My GUI contains a jPanel that on receiving a mouseclick, paints a point with filloval command.
private void myPnlMousePressed(java.awt.event.MouseEvent evt) {
changed = true;
p.x = evt.getX();
p.y = evt.getY();
drewPoints(p.x, p.y);
}
private void drewPoints (int x, int y) {
if (gf == null) {
gf = (Graphics)myPnl.getGraphics();
}
myPointsList.add(new Point(x, y));
gf.fillOval(x, y, 5, 5);
xVal.setText("X = " + x);
yVal.setText("Y = " + y);
}
everything works fine but when I want to open an XML file that I created to save all the points it doesn't work.
The problem is that when I use the repaint method on the jPanel after choosing a file, all the points loads fine but the panel can't draw the points.
If I put the repaint method in the open button listener (before the choosing file) it works, but then if the user cancels the open option so the panel stays blank and I don't want to draw the points again.
I think it happens because the repaint process is not finished.
All the points added to a private List.
private void OpenFile() {
try {
File thisFile;
JFileChooser of = new JFileChooser();
int option = of.showOpenDialog(of);
if (option == JFileChooser.APPROVE_OPTION){
thisFileName = of.getSelectedFile().getPath();
thisFile = new File(thisFileName);
if (!of.getSelectedFile().getName().endsWith(".xml")) {
String error = "Error, You didn't select XML file";
JOptionPane.showMessageDialog(this, error, "Wrong type of file", JOptionPane.INFORMATION_MESSAGE);
return;
}
myPnl.repaint();
myPointsList.clear();
....
....
....
for (int i = 0; i < pointsList.getLength(); i++) {
Element point = (Element) pointsList.item(i);
p.x = Integer.parseInt(point.getElementsByTagName("X").item(0).getTextContent());
p.y = Integer.parseInt(point.getElementsByTagName("Y").item(0).getTextContent());
drewPoints(p.x, p.y);
}
....
how can I make it work??
Don't use gf = (Graphics)myPnl.getGraphics();, this is not how painting in Swing works. The getGraphics method can return null and is nothing more then a snap shot of the last paint cycle, any thing you paint to it will be erased on the next paint cycle (repaint).
Instead, override the JPanels paintComponent and put all you painting logic there. There is an expectation that when called, you are expected to fully re-paint the current state of the component.
See Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing
You have to use the repaint() and override the paint() method:
class MyPanel extends JPanel implements MouseListener
{
private int x;
private int y;
public MyPanel() {
super();
addMouseListener(this);
}
#Override public void mouseEntered(MouseEvent e) { }
#Override public void mouseExited(MouseEvent e) { }
#Override public void mouseClicked(MouseEvent e) { }
#Override public void mousePressed(MouseEvent e) { }
#Override public void mouseReleased(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
#Override public void paint(Graphics g) {
super.paint(g);
g.fillOval(x, y, 10, 10);
}
}
If you want to draw all points, don't use x and y but a list of points:
class MyPanel extends JPanel implements MouseListener
{
private ArrayList<Point> points = new ArrayList<>();
public MyPanel() {
super();
addMouseListener(this);
}
#Override public void mouseEntered(MouseEvent e) { }
#Override public void mouseExited(MouseEvent e) { }
#Override public void mouseClicked(MouseEvent e) { }
#Override public void mousePressed(MouseEvent e) { }
#Override public void mouseReleased(MouseEvent e) {
points.add(new Point(e.getX(), e.getY()));
repaint();
}
#Override public void paint(Graphics g) {
super.paint(g);
for (Point p : points)
g.fillOval(p.getX(), p.getY(), 10, 10);
}
}
where:
class Point
{
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Then use it:
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
MyPanel myPanel = new MyPanel();
frame.add(myPanel);
frame.setVisible(true);
}

Java repaint() not working

I am making a simple program to paint a graph and some points in it. The points should be made with methods while changing coordinates of the g.fillOval but actually its painting only the last point.
Here is the code:
import javax.swing.*;
import java.awt.*;
public class PointGraphWriter extends JPanel
{
JFrame korniza = new JFrame();
private int x;
private int y;
private int length;
private String OX;
private String OY;
private String emri;
private int y_height;
private int x_num;
public PointGraphWriter()
{
int width= 500;
korniza.setSize(width,width);
korniza.setVisible(true);
korniza.setTitle(emri);
korniza.getContentPane().add(this);
}
public void paintComponent(Graphics g)
{
g.drawLine(x,y,x+length,y);
g.drawLine(x,y,x,y-length);
g.drawString(OX,x+length, y+15);
g.drawString(OY,x-15,y-length);
g.drawString("0", x -15,y);
g.drawString("0", x,y+15);
g.fillOval(x_num,y-y_height-2, 4 ,4);
}
public void setTitle(String name)
{
emri= name;
this.repaint();
}
public void setAxes(int x_pos, int y_pos, int axis_length, String x_label, String y_label)
{
x= x_pos;
y=y_pos;
length= axis_length;
OX = x_label;
OY = y_label;
}
public void setPoint1(int height)
{
y_height=height;
x_num = x-2;
this.repaint();
}
public void setPoint2(int height)
{
y_height=height;
x_num = x + length/5-2;
this.repaint();
}
}
and here is the main method:
public class TestPlot
{
public static void main(String[] a)
{
PointGraphWriter e = new PointGraphWriter();
e.setTitle("Graph of y = x*x");
e.setAxes(50, 110, 90, "5", "30");
int scale_factor = 3;
e.setPoint1(0 * scale_factor);
e.setPoint2(1 * scale_factor);
}
}
Please have a look at this example. Something in lines of this, you might have to incorporate in your example, to make it work. Simply use a Collection to store what you have previously painted, and when the new thingy comes along, simply add that thingy to the list, and repaint the whole Collection again. As shown below :
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
public class RectangleExample {
private DrawingBoard customPanel;
private JButton button;
private Random random;
private java.util.List<Rectangle2D.Double> rectangles;
private ActionListener buttonActions =
new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
Rectangle2D.Double rectangle = new Rectangle2D.Double(
(double) random.nextInt(100), (double) random.nextInt(100),
(double) random.nextInt(100), (double) random.nextInt(100));
rectangles.add(rectangle);
customPanel.setValues(rectangles);
}
};
public RectangleExample() {
rectangles = new ArrayList<Rectangle2D.Double>();
random = new Random();
}
private void displayGUI() {
JFrame frame = new JFrame("Rectangle Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout(5, 5));
customPanel = new DrawingBoard();
contentPane.add(customPanel, BorderLayout.CENTER);
button = new JButton("Create Rectangle");
button.addActionListener(buttonActions);
contentPane.add(button, BorderLayout.PAGE_END);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new RectangleExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
class DrawingBoard extends JPanel {
private java.util.List<Rectangle2D.Double> rectangles =
new ArrayList<Rectangle2D.Double>();
public DrawingBoard() {
setOpaque(true);
setBackground(Color.WHITE);
}
public void setValues(java.util.List<Rectangle2D.Double> rectangles) {
this.rectangles = rectangles;
repaint();
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(300, 300));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Rectangle2D.Double rectangle : rectangles) {
g.drawRect((int)rectangle.getX(), (int)rectangle.getY(),
(int)rectangle.getWidth(), (int)rectangle.getHeight());
}
System.out.println("WORKING");
}
}
See Custom Painting Approaches for examples of the two common ways to do painting:
Keep a List of the objects to be painted
Paint onto a BufferedImage
The approach you choose will depend on your exact requirement.

Is there a better way to set an initial position for a JPanel graphic?)

In Chapter 15 of Liang's Intro to Java Programming (7th ed.), he introduces a program to make a (2-D) ball on a JPanel and enlarge it upon clicking enlarge/shrink buttons. I've modified the program so that it also 1) enlarges/shrinks the ball if the user clicks/option+clicks, 2) allows you to pick the color of the ball by pressing a button, and 3) allows you to move the circle by dragging it with your mouse.
The last modification is what was giving me trouble for a while, because I wanted to center the ball at the beginning, but then allow the user to move the ball around with the mouse. The solution I came up with was to have the paintComponent method only set the x- and y-coordinates of the ball relative to getWidth() and getHeight() the first time it paints. To do that, I added a paintCount variable to the BallCanvas class and made an if statement so that it would only execute the first time around. When I was trying to figure out how to do this initially, I saw other solutions, like the ones given here: Why can't I access my panel's getWidth() and getHeight() functions? , but I find my solution much simpler.
So the question is: is what I did considered bad coding style? Would a professional programmer scoff at this solution? Or is it OK?
More importantly, is there a better (but also, relatively simple) way to do this that doesn't involve setting up a counter?
Here are the relevant bits of code:
The beginning of BallCanvas:
public static class BallCanvas extends JPanel {
private int radius = 20;
private Color color = Color.BLACK;
private int ballX;
private int ballY;
private int paintCount = 0;
...
The move method (which responds to a MouseDragged event):
public void move(MouseEvent e){
ballX = e.getX() - radius;
ballY = e.getY() - radius;
repaint();
}
The paintComponent method:
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(color);
if(paintCount < 1){
ballX = getWidth()/2 - radius;
ballY = getHeight()/2 - radius;
}
g.fillOval(ballX, ballY, 2*radius, 2*radius);
paintCount++;
}
Full program:
// Reference: Liang's Intro to Java Programming
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ControlBall extends JFrame{
private JButton jbtRed = new JButton("Red");
private JButton jbtGreen = new JButton("Green");
private JButton jbtBlue = new JButton("Blue");
private JButton jbtBlack = new JButton("Black");
private BallCanvas canvas = new BallCanvas();
private JMenuBar menuBar = new JMenuBar();
private JMenu menu = new JMenu("Edit");
private JMenuItem miEnlarge = new JMenuItem("Enlarge");
private JMenuItem miShrink = new JMenuItem("Shrink");
public ControlBall(){
menuBar.add(menu);
menu.add(miEnlarge);
menu.add(miShrink);
JPanel panel = new JPanel();
panel.add(jbtRed);
panel.add(jbtGreen);
panel.add(jbtBlue);
panel.add(jbtBlack);
this.add(canvas, BorderLayout.CENTER);
this.add(panel, BorderLayout.SOUTH);
this.add(menuBar, BorderLayout.NORTH);
jbtRed.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.RED);
}
});
jbtGreen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.GREEN);
}
});
jbtBlue.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.BLUE);
}
});
jbtBlack.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.BLACK);
}
});
miEnlarge.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.enlarge();
}
});
miShrink.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.shrink();
}
});
canvas.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e){
canvas.changeSize(e);
}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
});
canvas.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
canvas.move(e);
}
});
}
public static void main(String[] args){
JFrame frame = new ControlBall();
frame.setTitle("ControlBall");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
frame.setVisible(true);
}
public static class BallCanvas extends JPanel {
private int radius = 20;
private Color color = Color.BLACK;
private int ballX;
private int ballY;
private int paintCount = 0;
public BallCanvas(){
System.out.println(getWidth() + " " + getHeight());
}
public BallCanvas(int initialRadius){
radius = initialRadius;
}
public void setColor(Color color){
this.color = color;
repaint();
}
public void changeSize(MouseEvent e){
int numClicks = e.getClickCount();
if(e.isAltDown()){
if(radius >= 6){
this.radius -= 5*numClicks;
} else{
// do nothing
}
} else{
this.radius += 5*numClicks;
}
repaint();
}
public void enlarge(){
this.radius += 5;
repaint();
}
public void shrink(){
if(radius >= 10){
this.radius -= 5;
}
repaint();
}
public void move(MouseEvent e){
ballX = e.getX() - radius;
ballY = e.getY() - radius;
repaint();
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(color);
if(paintCount < 1){
ballX = getWidth()/2 - radius;
ballY = getHeight()/2 - radius;
}
g.fillOval(ballX, ballY, 2*radius, 2*radius);
paintCount++;
}
}
}
Several things merit attention:
Override getPreferredSize() to establish the panel's initial geometry.
Use that geometry to establish the ball's initial position.
Invoke pack() and then set the location & visibility.
Use Action to encapsulate code shared by menus and controls.
Use adapters consistently.
Use initial threads correctly.
See this Q&A, which examines a related example from several perspectives.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ControlBall extends JFrame {
private JButton jbtRed = new JButton("Red");
private JButton jbtGreen = new JButton("Green");
private JButton jbtBlue = new JButton("Blue");
private JButton jbtBlack = new JButton("Black");
private BallCanvas canvas = new BallCanvas();
private JMenuBar menuBar = new JMenuBar();
private JMenu menu = new JMenu("Edit");
private JMenuItem miEnlarge = new JMenuItem("Enlarge");
private JMenuItem miShrink = new JMenuItem("Shrink");
public ControlBall() {
menuBar.add(menu);
menu.add(miEnlarge);
menu.add(miShrink);
JPanel panel = new JPanel();
panel.add(jbtRed);
panel.add(jbtGreen);
panel.add(jbtBlue);
panel.add(jbtBlack);
this.add(canvas, BorderLayout.CENTER);
this.add(panel, BorderLayout.SOUTH);
this.add(menuBar, BorderLayout.NORTH);
jbtRed.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
canvas.setColor(Color.RED);
}
});
jbtGreen.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
canvas.setColor(Color.GREEN);
}
});
jbtBlue.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
canvas.setColor(Color.BLUE);
}
});
jbtBlack.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
canvas.setColor(Color.BLACK);
}
});
miEnlarge.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
canvas.enlarge();
}
});
miShrink.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
canvas.shrink();
}
});
canvas.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
canvas.changeSize(e);
}
#Override
public void mouseDragged(MouseEvent e) {
canvas.move(e);
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new ControlBall();
frame.setTitle("ControlBall");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class BallCanvas extends JPanel {
private static final int SIZE = 400;
private int radius = 20;
private Color color = Color.BLACK;
private int ballX = SIZE / 2 - radius;
private int ballY = SIZE / 2 - radius;
public BallCanvas() {
System.out.println(getWidth() + " " + getHeight());
}
public BallCanvas(int initialRadius) {
radius = initialRadius;
}
public void setColor(Color color) {
this.color = color;
repaint();
}
public void changeSize(MouseEvent e) {
int numClicks = e.getClickCount();
if (e.isAltDown()) {
if (radius >= 6) {
this.radius -= 5 * numClicks;
} else {
// do nothing
}
} else {
this.radius += 5 * numClicks;
}
repaint();
}
public void enlarge() {
this.radius += 5;
repaint();
}
public void shrink() {
if (radius >= 10) {
this.radius -= 5;
}
repaint();
}
public void move(MouseEvent e) {
ballX = e.getX() - radius;
ballY = e.getY() - radius;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillOval(ballX, ballY, 2 * radius, 2 * radius);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
}
}

adding squares to an animation

I'm trying to create a program that runs an animation similar to the one on this video but I'm having trouble adding more squares. I tried to add all the squares to an array list but I couldn't figure out where it goes.
so far this is my code:
public class Animation extends JFrame{
CrazySquares square = new CrazySquares();
Animation(){
add(new CrazySquares());
}
public static void main (String[] args){
Animation frame = new Animation();
frame.setTitle("AnimationDemo");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(250, 250);
frame.setVisible(true);
}
}
class CrazySquares extends JPanel{
private final int numberOfRectangles=100;
Color color=new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256));
private int x=1;
private int y=1;
private Timer timer = new Timer(30, new TimerListener());
Random random= new Random();
int randomNumber=1+(random.nextInt(4)-2);
Random rand= new Random();
int rando=1+(rand.nextInt(4)-2);
CrazySquares(){
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width=getWidth();
int height=getHeight();
g.setColor(color);
g.fillRect(x+width/2,y+(int)(height*.47), 20, 20);
}
class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
x += rando;
y+= randomNumber;
repaint();
}
}
}
You've got code to paint out one rectangle, here:
int width=getWidth();
int height=getHeight();
g.setColor(color);
g.fillRect(x+width/2,y+(int)(height*.47), 20, 20);
Now what I would recommend, would be that you port these values into a Square object. Or, better yet, use the Rectangle object. If you went with the custom approach:
public class Square
{
public Square(int x, int y, int height, int width)
{
// Store these values in some fields.
}
public void paintComponent(Graphics g)
{
g.fillRect() // Your code for painting out squares.
}
}
Then, all you need to do, is call each object's paintComponent method in some list. Let's assume you have some List:
List<Square> squares = new ArrayList<Square>();
for(Square sq : squares)
{
sq.paintComponent(g);
}
this is the code so far. I know its nasty but its because i've been trying different things a none of them work. i really appreciate your help. thanks. #ChrisCooney
public class SquaresAnimation extends JFrame{
SquaresAnimation(){
add(new CrazySquares());
}
public static void main (String[] args){
SquaresAnimation frame = new SquaresAnimation();
frame.setTitle("AnimationDemo");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(250, 250);
frame.setVisible(true);
}
}
class Square{
private int x;
private int y;
public int height;
public int width;
Square(int x, int y, int height, int width)
{
// Store these values in some fields.
this.x=x;
this.y=y;
this.height=height;
this.width=width;
}
public void paintComponent(Graphics g)
{
g.setColor(Color.CYAN);
g.fillRect(x+width/2,y+(int)(height*.47), 20, 20);
}
}
class CrazySquares extends JPanel {
private final int numberOfRectangles=100;
Color color=new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256));
private int x=1;
private int y=1;
Random random= new Random();
int randomNumber=1+(random.nextInt(4)-2);
Random rand= new Random();
int rando=1+(rand.nextInt(4)-2);
private Timer timer = new Timer(30, new TimerListener());
List<Square> squares = new ArrayList<Square>();
CrazySquares(Graphics g){
timer.start();
for(Square sq : squares){
sq.paintComponent(g);
}
}
}
//protected void paintComponent(Graphics g) {
//super.paintComponent(g);
// }
class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}

Press and Drag in One Click?

I have a program where I am creating a JLabel on a click and then dragging that to another portion of the interface.
What I want is to click somewhere in the JPanel, have it drop a JLabel there, and then drag another JLabel all in the same click.
I am able to do this, but it takes multiple clicks. Can I do it in one click?
To illustrate what I mean, I created this sample program:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragTest extends JFrame implements MouseMotionListener,
MouseListener {
private JPanel panel = new JPanel(null);
private JLabel dragLabel = new JLabel("drag");;
private final JWindow window = new JWindow();
public DragTest() {
this.add(panel);
panel.addMouseListener(this);
dragLabel.setFont(new Font("Serif", Font.BOLD, 48));
}
#Override
public void mouseDragged(MouseEvent me) {
dragLabel = new JLabel("drag");
dragLabel.setFont(new Font("Serif", Font.BOLD, 48));
int x = me.getPoint().x;
int y = me.getPoint().y;
window.add(dragLabel);
window.pack();
Point pt = new Point(x, y);
Component c = (Component) me.getSource();
SwingUtilities.convertPointToScreen(pt, c);
window.setLocation(pt);
window.setVisible(true);
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
JLabel dropLabel = new JLabel("drop");
panel.add(dropLabel);
dropLabel.setForeground(Color.RED);
dropLabel.setFont(new Font("Serif", Font.BOLD, 48));
dropLabel.setBounds(e.getX(), e.getY(), 100, 60);
dropLabel.addMouseMotionListener(this);
dropLabel.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
dragLabel.setVisible(false);
window.setVisible(false);
}
});
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
public static void main(String[] args) {
DragTest frame = new DragTest();
frame.setVisible(true);
frame.setSize(600, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
So the initial click creates the "drop" JLabel, and then clicking on and dragging on the "drop" JLabel will create a "drag" JLabel that follows the mouse around.
How can I do this in one click and drag?
Don't create a new JLabel in the mouseDragged method but rather use the same JLabel. For example:
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class DragTest2 extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = 400;
private static final float LABEL_PTS = 24f;
private static final String LABEL_TEXT = "My Label";
private JLabel label = null;
public DragTest2() {
setLayout(null);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
label = new JLabel(LABEL_TEXT);
label.setFont(label.getFont().deriveFont(LABEL_PTS));
Dimension labelSize = label.getPreferredSize();
label.setSize(labelSize);
int x = e.getX() - labelSize.width / 2;
int y = e.getY() - labelSize.height / 2;
label.setLocation(x , y);
add(label);
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
if (label != null) {
Dimension labelSize = label.getPreferredSize();
int x = e.getX() - labelSize.width / 2;
int y = e.getY() - labelSize.height / 2;
label.setLocation(x , y);
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (label != null) {
Dimension labelSize = label.getPreferredSize();
int x = e.getX() - labelSize.width / 2;
int y = e.getY() - labelSize.height / 2;
label.setLocation(x , y);
repaint();
label = null;
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("DragTest2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DragTest2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Categories

Resources