问题
The Problem is when I resize the JFrame
the animation goes on with it's Pre supplied dimensions for JComponent
. Is there a way that I can update my width
and height
variables as I resize the JFrame
, so that the Animation can run along with the new Co-ordinates.
In simpler terms, say the JComponent
has initial width = 300
and height = 300
, so the BALL
moves inside these specified Co-ordinates
. Now if I resize my JFrame
, the size for the JComponent
still remains as is i.e. width = 300
and height = 300
, but what I was hoping for, is a way to modify these variables with the present size of the window. Do let me know if I lack something in explaining my issue.
Here is the code that I am using :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BallAnimation
{
private int x;
private int y;
private int count;
private int width;
private int height;
private int speedValue;
private boolean flag;
/*
* These variables are used to keep track of
* the ball, either it is going LEFT or RIGHT
* depending on that, we will set the
* Co-ordinates.
*/
private boolean toLeft, toRight;
private boolean fromTop, fromBottom;
private Timer timer;
private JButton button;
private ActionListener actionTimer;
private ActionListener buttonAction;
public BallAnimation()
{
x = y = count = 0;
flag = toLeft = false;
toRight = true;
fromTop = true;
fromBottom = false;
speedValue = 5;
}
public static void main(String args[])
{
Runnable runnable = new Runnable()
{
public void run()
{
BallAnimation animation = new BallAnimation();
animation.go();
}
};
SwingUtilities.invokeLater(runnable);
}
public void go()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel contentPane = new JPanel();
/*
* Class Name :
* Java Naming Convention says that class names
* should be in Pascal Case, i.e. the first
* letter of the class name should be capitalized
* and every new word must start with a capitalized
* Alphabet.
* For Example :
* public class ClassName{...}
* ----------------------------------------------------------
* Variable Name :
* Java Naming Convention says that the variable name
* should be in Camel Case, i.e. the first letter of
* the variable name should be small case or _ (underscore)
* and every new word must start with a capitalized
* Alphabet.
* ---------------------------------------------------------
*/
final MyDraw drawPanel = new MyDraw(0, 0);
x = drawPanel.getXValue();
y = drawPanel.getYValue();
//contentPane.add(drawPanel);
actionTimer = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
if (fromTop && !fromBottom && x < width && y < height
&& toRight && !toLeft)
{
x += speedValue;
y += speedValue;
}
else if (fromTop && !fromBottom && x < width && y >= height
&& toRight && !toLeft)
{
/*
* Since the ball coming from the TOP LEFT Side
* touched the BOTTOM of the JPanel.
*/
y -= speedValue;
x += speedValue;
fromTop = false;
fromBottom = true;
}
else if (!fromTop && fromBottom && x < width && y <= 0
&& toRight && !toLeft)
{
/*
* Since the ball coming from BOTTOM LEFT Side
* touched the TOP of the JPanel.
*/
fromTop = true;
fromBottom = false;
x += speedValue;
y += speedValue;
}
else if (!fromTop && fromBottom && x < width && y < height
&& toRight && !toLeft)
{
x += speedValue;
y -= speedValue;
}
else if (!fromTop && fromBottom && x >= width && y < height
&& toRight && !toLeft)
{
/*
* Since the ball coming from the BOTTOM LEFT Side
* touched the RIGHT Side of the JPanel.
*/
toRight = false;
toLeft = true;
x -= speedValue;
y -= speedValue;
}
else if (!fromTop && fromBottom && x < width && y <= 0
&& !toRight && toLeft)
{
/*
* Since the ball coming from the BOTTOM RIGHT Side
* touched the Top Side of the JPanel.
*/
fromTop = true;
fromBottom = false;
x -= speedValue;
y += speedValue;
}
else if (fromTop && !fromBottom && x <= 0 && y < height
&& !toRight && toLeft)
{
/*
* Since the ball coming from the TOP RIGHT Side
* touched the LEFT Side of the JPanel.
*/
toRight = true;
toLeft = false;
x += speedValue;
y += speedValue;
}
else if (fromTop && !fromBottom && x >= width && y < height
&& toRight && !toLeft)
{
/*
* Since the ball coming from the TOP LEFT Side
* touched the RIGHT Side of the JPanel
*/
toRight = false;
toLeft = true;
x -= speedValue;
y += speedValue;
}
else if (fromTop && !fromBottom && x < width && y < height
&& !toRight && toLeft)
{
x -= speedValue;
y += speedValue;
}
else if (!fromTop && fromBottom && x <= 0 && y < height
&& !toRight && toLeft)
{
/*
* Since the ball coming from the BOTTOM RIGHT Side
* touched the LEFT Side of the JPanel.
*/
toRight = true;
toLeft = false;
x += speedValue;
y -= speedValue;
}
else if (!fromTop && fromBottom && x < width && y < height
&& !toRight && toLeft)
{
x -= speedValue;
y -= speedValue;
}
else if (fromTop && !fromBottom && x < width && y >= height
&& !toRight && toLeft)
{
/*
* Since the ball coming from the TOP RIGHT Side
* touched the BOTTOM Side of the JPanel.
*/
fromTop = false;
fromBottom = true;
x -= speedValue;
y -= speedValue;
}
System.out.println("X : " + x);
System.out.println("Y : " + y);
System.out.println("Direction is LEFT : " + toLeft);
System.out.println("Direction is RIGHT : " + toRight);
System.out.println("Coming from TOP : " + fromTop);
System.out.println("Coming from BOTTOM : " + fromBottom);
drawPanel.setXYValues(x, y);
}
};
buttonAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
if (!flag)
{
timer.start();
button.setText("STOP ANIMATION");
flag = true;
}
else if (flag)
{
timer.stop();
button.setText("START ANIMATION");
flag = false;
}
}
};
button = new JButton("START ANIMATION");
button.addActionListener(buttonAction);
frame.getContentPane().add(drawPanel, BorderLayout.CENTER);
frame.getContentPane().add(button, BorderLayout.PAGE_END);
frame.setSize(300, 300);
//frame.pack();
frame.setVisible(true);
timer = new Timer(40, actionTimer);
width = drawPanel.getWidth() - 30;
System.out.println("WIDTH : " + width);
height = drawPanel.getHeight() - 30;
System.out.println("HEIGHT : " + height);
}
class MyDraw extends JComponent
{
private int x;
private int y;
private Timer timer;
public MyDraw(int x, int y)
{
this.x = x;
this.y = y;
}
public int getXValue()
{
return x;
}
public int getYValue()
{
return y;
}
public void setXYValues(int x, int y)
{
this.x = x;
this.y = y;
repaint();
}
public Dimension getPreferredSize()
{
return (new Dimension(300, 300));
}
public void paintComponent(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLUE);
g.fillOval(x, y, 40, 40);
}
}
}
回答1:
Now that is a whole heapin' helping of code! Try this variant (breaks one or two things, but fixes the main problem). The fix is to base the width/height on the current size of the component.
package test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BallAnimation
{
private int x;
private int y;
private int count;
//private int drawPanel.getWidth();
//private int drawPanel.getHeight();
private int speedValue;
private boolean flag;
/*
* These variables are used to keep track of
* the ball, either it is going LEFT or RIGHT
* depending on that, we will set the
* Co-ordinates.
*/
private boolean toLeft, toRight;
private boolean fromTop, fromBottom;
private Timer timer;
private JButton button;
private ActionListener actionTimer;
private ActionListener buttonAction;
MyDraw drawPanel;
public BallAnimation()
{
x = y = count = 0;
flag = toLeft = false;
toRight = true;
fromTop = true;
fromBottom = false;
speedValue = 5;
}
public static void main(String args[])
{
Runnable runnable = new Runnable()
{
public void run()
{
BallAnimation animation = new BallAnimation();
animation.go();
}
};
SwingUtilities.invokeLater(runnable);
}
public void go()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel contentPane = new JPanel();
/*
* Class Name :
* Java Naming Convention says that class names
* should be in Pascal Case, i.e. the first
* letter of the class name should be capitalized
* and every new word must start with a capitalized
* Alphabet.
* For Example :
* public class ClassName{...}
* ----------------------------------------------------------
* Variable Name :
* Java Naming Convention says that the variable name
* should be in Camel Case, i.e. the first letter of
* the variable name should be small case or _ (underscore)
* and every new word must start with a capitalized
* Alphabet.
* ---------------------------------------------------------
*/
drawPanel = new MyDraw(0, 0);
x = drawPanel.getXValue();
y = drawPanel.getYValue();
//contentPane.add(drawPanel);
actionTimer = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
if (fromTop && !fromBottom && x < drawPanel.getWidth() && y < drawPanel.getHeight()
&& toRight && !toLeft)
{
x += speedValue;
y += speedValue;
}
else if (fromTop && !fromBottom && x < drawPanel.getWidth() && y >= drawPanel.getHeight()
&& toRight && !toLeft)
{
/*
* Since the ball coming from the TOP LEFT Side
* touched the BOTTOM of the JPanel.
*/
y -= speedValue;
x += speedValue;
fromTop = false;
fromBottom = true;
}
else if (!fromTop && fromBottom && x < drawPanel.getWidth() && y <= 0
&& toRight && !toLeft)
{
/*
* Since the ball coming from BOTTOM LEFT Side
* touched the TOP of the JPanel.
*/
fromTop = true;
fromBottom = false;
x += speedValue;
y += speedValue;
}
else if (!fromTop && fromBottom && x < drawPanel.getWidth() && y < drawPanel.getHeight()
&& toRight && !toLeft)
{
x += speedValue;
y -= speedValue;
}
else if (!fromTop && fromBottom && x >= drawPanel.getWidth() && y < drawPanel.getHeight()
&& toRight && !toLeft)
{
/*
* Since the ball coming from the BOTTOM LEFT Side
* touched the RIGHT Side of the JPanel.
*/
toRight = false;
toLeft = true;
x -= speedValue;
y -= speedValue;
}
else if (!fromTop && fromBottom && x < drawPanel.getWidth() && y <= 0
&& !toRight && toLeft)
{
/*
* Since the ball coming from the BOTTOM RIGHT Side
* touched the Top Side of the JPanel.
*/
fromTop = true;
fromBottom = false;
x -= speedValue;
y += speedValue;
}
else if (fromTop && !fromBottom && x <= 0 && y < drawPanel.getHeight()
&& !toRight && toLeft)
{
/*
* Since the ball coming from the TOP RIGHT Side
* touched the LEFT Side of the JPanel.
*/
toRight = true;
toLeft = false;
x += speedValue;
y += speedValue;
}
else if (fromTop && !fromBottom && x >= drawPanel.getWidth() && y < drawPanel.getHeight()
&& toRight && !toLeft)
{
/*
* Since the ball coming from the TOP LEFT Side
* touched the RIGHT Side of the JPanel
*/
toRight = false;
toLeft = true;
x -= speedValue;
y += speedValue;
}
else if (fromTop && !fromBottom && x < drawPanel.getWidth() && y < drawPanel.getHeight()
&& !toRight && toLeft)
{
x -= speedValue;
y += speedValue;
}
else if (!fromTop && fromBottom && x <= 0 && y < drawPanel.getHeight()
&& !toRight && toLeft)
{
/*
* Since the ball coming from the BOTTOM RIGHT Side
* touched the LEFT Side of the JPanel.
*/
toRight = true;
toLeft = false;
x += speedValue;
y -= speedValue;
}
else if (!fromTop && fromBottom && x < drawPanel.getWidth() && y < drawPanel.getHeight()
&& !toRight && toLeft)
{
x -= speedValue;
y -= speedValue;
}
else if (fromTop && !fromBottom && x < drawPanel.getWidth() && y >= drawPanel.getHeight()
&& !toRight && toLeft)
{
/*
* Since the ball coming from the TOP RIGHT Side
* touched the BOTTOM Side of the JPanel.
*/
fromTop = false;
fromBottom = true;
x -= speedValue;
y -= speedValue;
}
System.out.println("X : " + x);
System.out.println("Y : " + y);
System.out.println("Direction is LEFT : " + toLeft);
System.out.println("Direction is RIGHT : " + toRight);
System.out.println("Coming from TOP : " + fromTop);
System.out.println("Coming from BOTTOM : " + fromBottom);
drawPanel.setXYValues(x, y);
}
};
buttonAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
if (!flag)
{
timer.start();
button.setText("STOP ANIMATION");
flag = true;
}
else if (flag)
{
timer.stop();
button.setText("START ANIMATION");
flag = false;
}
}
};
button = new JButton("START ANIMATION");
button.addActionListener(buttonAction);
frame.getContentPane().add(drawPanel, BorderLayout.CENTER);
frame.getContentPane().add(button, BorderLayout.PAGE_END);
frame.setSize(300, 300);
//frame.pack();
frame.setVisible(true);
timer = new Timer(40, actionTimer);
System.out.println("WIDTH : " + drawPanel.getWidth());
System.out.println("HEIGHT : " + drawPanel.getHeight());
}
class MyDraw extends JComponent
{
private int x;
private int y;
private Timer timer;
public MyDraw(int x, int y)
{
this.x = x;
this.y = y;
}
public int getXValue()
{
return x;
}
public int getYValue()
{
return y;
}
public void setXYValues(int x, int y)
{
this.x = x;
this.y = y;
repaint();
}
public Dimension getPreferredSize()
{
return (new Dimension(300, 300));
}
public void paintComponent(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLUE);
g.fillOval(x, y, 40, 40);
}
}
}
回答2:
just simply need to addHierarchyBoundsListener(...), to your MyDraw
object, i.e. drawPanel
, like as explained below :
private HierarchyBoundsListener boundsListener =
new HierarchyBoundsListener()
{
public void ancestorMoved(HierarchyEvent he)
{
}
public void ancestorResized(HierarchyEvent he)
{
JComponent component = (JComponent) he.getComponent();
width = component.getWidth() - 30;
height = component.getHeight() - 30;
}
};
And to add this to your drawPanel
object, you be doing :
drawPanel.addHierarchyBoundsListener(boundsListener);
回答3:
I expect you just need to bind some variety of listener (WindowEventListener
?) to the JFrame, so that width
and height
are updated whenever the window dimensions change.
来源:https://stackoverflow.com/questions/9800968/ball-animation-in-swing