[英]How to animate two separate balls Java AWT & Swing
所以我在玩 java GUI。 我正在编写一个程序,当球击中 window 的末端时,它会弹起。go 如何更新secondBall
以更新并显示其新位置? secondBall.action();
不起作用。 请参阅以下代码中的THIS DOES NOT WORK 。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// Ball. This class describes the concept of ball. A ball has a position
// (given by a coordinate (x,y)), a velocity (given by a
// differential (dx,dy)) and a color.
class Ball {
// Default constants (for all instances of Ball)
static int defaultDiameter = 10;
static Color defaultColor = Color.yellow;
static Rectangle defaultBox = new Rectangle(0,0,100,100);
// Position
private int x, y;
// Speed and direction
private int dx, dy;
// Diameter (size)
private int diameter;
// Color
private Color color;
// Bounding rectangular area within which the ball bounces
private Rectangle box;
// Construction of new balls requires position and direction
public Ball( int x0, int y0, int dx0, int dy0 ) {
x = x0;
y = y0;
dx = dx0;
dy = dy0;
color = defaultColor;
diameter = defaultDiameter;
}
// Set new color
public void setColor( Color c ) {
color = c;
}
// Set new bounding rectangular area
public void setBoundingBox( Rectangle r ) {
box = r;
}
// Set new diameter
public void setDiameter(int newDiameter) {
diameter = newDiameter;
}
// Draw a ball on given graphic area
public void paint( Graphics g ) {
// Change to the color of the ball
g.setColor( color.WHITE );
// The ball is represented as a filled circle, i.e. an ellipse (oval)
// with equal height and width
g.fillOval( x, y, diameter, diameter );
}
// Constrain the ball within the rectangular area. Update the speed
// if necessary.
void constrain() {
// Give absolute coordinates of the rectangular area
int x0 = box.x;
int y0 = box.y;
int x1 = x0 + box.width - diameter;
int y1 = y0 + box.height - diameter;
// Change speed and direction if the ball is outside of it
// rectangular area
if (x < x0) {
dx = Math.abs(dx);
}
if (x > x1) {
dx = -Math.abs(dx);
}
if (y < y0) {
dy = Math.abs(dy);
}
if (y > y1) {
dy = -Math.abs(dy);
}
}
// Move the ball with the current direction and speed one step
public void action() {
x = x + dx;
y = y + dy;
constrain();
}
}
// The BallPanel class defines a drawing surface where the balls are drawn. The
// inherits the JPanel class and implements ActionListener. By
// implement ActionListener you can let a Timer with even
// spaces give a 'tick' when updating the panel should be done.
class BallPanel extends JPanel implements ActionListener {
// Width and height
private int width, height;
// A ball
private Ball ball;
private Ball secondBall;
// Timer. Sends a signal every 50 milliseconds to the panel which
// sent along as ActionListener.
private Timer timer = new Timer(50, this);
// Initialize the attributes
public BallPanel(int width, int height) {
// Find out the width and height of the artboard
this.width = width;
this.height = height;
// Create a new ball
ball = new Ball( width / 10, height / 5, 5, 5 );
secondBall = new Ball( width / 10, height / 5, 5, 5 );
// Set the ball's rectangular bounding box
ball.setBoundingBox( new Rectangle( 0, 0, width, height ) );
// Start the timer.
timer.start();
}
// Update (called on repaint, repaint())
public void paintComponent( Graphics g ) {
// Clear the entire drawing surface (with black color)
g.setColor( Color.black );
g.fillRect( 0, 0, getWidth(), getHeight() );
// Draw the ball (on black background)
ball.paint(g);
ball.setDiameter(15);
secondBall.paint(g);
secondBall.setDiameter(10);
}
// When we get a signal from the timer...
public void actionPerformed(ActionEvent e) {
if(width != getWidth() || height != getHeight())
wasResized();
ball.action();// Do whatever is relevant with the ball
// secondBall.action(); THIS DOES NOT WORK
repaint(); // Automatically make another call
// paintComponent()
}
// Called if window resizes
public void wasResized( ) {
//width = newWidth;
// height = newHeight;
ball.setBoundingBox(new Rectangle(0, 0, getWidth(), getHeight()));
}
}
// This class defines the window created by the program. One
// window (JFrame) is created where an instance of BallPanel (the artboard)
// placed.
public class BallWorld extends JFrame {
// Create a panel
private BallPanel panel = new BallPanel (180, 180);
public BallWorld() {
// Add the ball panel to the center of the frame.
Container c = getContentPane();
c.add(panel, BorderLayout.CENTER);
setSize(200, 200); // Frame size.
setLocation(100, 100); // So that the frame does not end up in a corner.
setVisible(true); // Make the frame visible.
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
// This method is started by the Java virtual machine when java is called
// BallWorld
public static void main(String args[]) {
// This command provides better animation in a part
// Olympics. Comment if the ball moves jerkily.
// System.setProperty("sun.java2d.opengl", "true");
BallWorld world = new BallWorld();
}
}
当尝试为secondBall
object 设置动画时,我遇到了错误。
我尝试添加secondBall.action();
就在ball.action();
在actionPerformed
方法中。
当尝试为
secondBall
object 设置动画时,我遇到了错误。
我尝试添加
secondBall.action();
就在ball.action();
在actionPerformed
方法中。
您应该在问题中发布错误详细信息。
当我运行您的代码(包括secondBall.action()
行)时,我得到:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot read field "x" because "this.box" is null
at swingprj/swngtsts.Ball.constrain(BallWorld.java:64)
at swingprj/swngtsts.Ball.action(BallWorld.java:88)
at swingprj/swngtsts.BallPanel.actionPerformed(BallWorld.java:139)
at java.desktop/javax.swing.Timer.fireActionPerformed(Timer.java:311)
at java.desktop/javax.swing.Timer$DoPostEvent.run(Timer.java:243)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:771)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:741)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
constrain()
方法(属于 class Ball
)的第一行抛出异常,即这一行:
int x0 = box.x;
那是因为box
是 null 而它是 null 因为您没有在 class BallPanel
的构造函数中为secondBall
调用方法setBoundingBox
。
因此,为了修复您的NullPointerException
,只需将此行添加到BallPanel
class 构造函数中:
secondBall.setBoundingBox();
这是带有添加行的代码(由注释表示: ADDED THIS LINE )
package swngtsts;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// Ball. This class describes the concept of ball. A ball has a position
// (given by a coordinate (x,y)), a velocity (given by a
// differential (dx,dy)) and a color.
class Ball {
// Default constants (for all instances of Ball)
static int defaultDiameter = 10;
static Color defaultColor = Color.yellow;
static Rectangle defaultBox = new Rectangle(0, 0, 100, 100);
// Position
private int x, y;
// Speed and direction
private int dx, dy;
// Diameter (size)
private int diameter;
// Color
private Color color;
// Bounding rectangular area within which the ball bounces
private Rectangle box;
// Construction of new balls requires position and direction
public Ball(int x0, int y0, int dx0, int dy0) {
x = x0;
y = y0;
dx = dx0;
dy = dy0;
color = defaultColor;
diameter = defaultDiameter;
}
// Set new color
public void setColor(Color c) {
color = c;
}
// Set new bounding rectangular area
public void setBoundingBox(Rectangle r) {
box = r;
}
// Set new diameter
public void setDiameter(int newDiameter) {
diameter = newDiameter;
}
// Draw a ball on given graphic area
public void paint(Graphics g) {
// Change to the color of the ball
g.setColor(color.WHITE);
// The ball is represented as a filled circle, i.e. an ellipse (oval)
// with equal height and width
g.fillOval(x, y, diameter, diameter);
}
// Constrain the ball within the rectangular area. Update the speed
// if necessary.
void constrain() {
// Give absolute coordinates of the rectangular area
int x0 = box.x;
int y0 = box.y;
int x1 = x0 + box.width - diameter;
int y1 = y0 + box.height - diameter;
// Change speed and direction if the ball is outside of it
// rectangular area
if (x < x0) {
dx = Math.abs(dx);
}
if (x > x1) {
dx = -Math.abs(dx);
}
if (y < y0) {
dy = Math.abs(dy);
}
if (y > y1) {
dy = -Math.abs(dy);
}
}
// Move the ball with the current direction and speed one step
public void action() {
x = x + dx;
y = y + dy;
constrain();
}
}
// The BallPanel class defines a drawing surface where the balls are drawn. The
// inherits the JPanel class and implements ActionListener. By
// implement ActionListener you can let a Timer with even
// spaces give a 'tick' when updating the panel should be done.
class BallPanel extends JPanel implements ActionListener {
// Width and height
private int width, height;
// A ball
private Ball ball;
private Ball secondBall;
// Timer. Sends a signal every 50 milliseconds to the panel which
// sent along as ActionListener.
private Timer timer = new Timer(50, this);
// Initialize the attributes
public BallPanel(int width, int height) {
// Find out the width and height of the artboard
this.width = width;
this.height = height;
// Create a new ball
ball = new Ball(width / 10, height / 5, 5, 5);
secondBall = new Ball(width / 10, height / 5, 5, 5);
// Set the ball's rectangular bounding box
ball.setBoundingBox(new Rectangle(0, 0, width, height));
secondBall.setBoundingBox(new Rectangle(0, 0, width, height)); // ADDED THIS LINE
// Start the timer.
timer.start();
}
// Update (called on repaint, repaint())
public void paintComponent(Graphics g) {
// Clear the entire drawing surface (with black color)
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
// Draw the ball (on black background)
ball.paint(g);
ball.setDiameter(15);
secondBall.paint(g);
secondBall.setDiameter(10);
}
// When we get a signal from the timer...
public void actionPerformed(ActionEvent e) {
if (width != getWidth() || height != getHeight())
wasResized();
ball.action();// Do whatever is relevant with the ball
secondBall.action(); //THIS DOES NOT WORK
repaint(); // Automatically make another call
// paintComponent()
}
// Called if window resizes
public void wasResized() {
// width = newWidth;
// height = newHeight;
ball.setBoundingBox(new Rectangle(0, 0, getWidth(), getHeight()));
}
}
// This class defines the window created by the program. One
// window (JFrame) is created where an instance of BallPanel (the artboard)
// placed.
public class BallWorld extends JFrame {
// Create a panel
private BallPanel panel = new BallPanel(180, 180);
public BallWorld() {
// Add the ball panel to the center of the frame.
Container c = getContentPane();
c.add(panel, BorderLayout.CENTER);
setSize(200, 200); // Frame size.
setLocation(100, 100); // So that the frame does not end up in a corner.
setVisible(true); // Make the frame visible.
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
// This method is started by the Java virtual machine when java is called
// BallWorld
public static void main(String args[]) {
// This command provides better animation in a part
// Olympics. Comment if the ball moves jerkily.
// System.setProperty("sun.java2d.opengl", "true");
BallWorld world = new BallWorld();
}
}
...很好,不要忘记修改第二个球的边界区域。
public void wasResized() {
// width = newWidth;
// height = newHeight;
ball.setBoundingBox(new Rectangle(0, 0, getWidth(), getHeight()));
secondBall.setBoundingBox(new Rectangle(0, 0, getWidth(), getHeight()));
//Adding new bounding to secondball
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.