gpt4 book ai didi

java - 通过 InvokeLater 的多个动画 - Java

转载 作者:行者123 更新时间:2023-12-02 05:48:30 25 4
gpt4 key购买 nike

我正在尝试制作一个 GUI,它本质上有多个弹跳球。这些球是通过 JButton 添加的。我能够成功地创建 Ball 类,并仅用一个球在屏幕上制作动画,但是我无法通过使用按钮添加多个球。我尝试制作一个 ActionListener 来创建新线程并调用 SwingUtilities.InvokeLater,但它只会使 GUI 卡住。我尝试按照本指南了解如何使用 InvokeLater:http://www.javamex.com/tutorials/threads/invokelater.shtml

这是到目前为止我的代码。任何帮助表示赞赏。 (我意识到之前已经在这里问过弹跳球问题,但我无法理解回复中解释的方法,并且认为我应该在这里问而不是评论一个2年前的问题)

球类

package BouncingBall;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Random;

public class Ball extends JComponent
{
private double dx;
private double dy;
private double x;
private double y;
private Color color;
private Random rand = new Random();
private Ellipse2D.Double ball;
private final static int diam = 10;
private final static int xLim = BallFrame.FRAME_WIDTH-diam;
private final static int yLim = BallFrame.FRAME_HEIGHT-diam*7;
boolean xUpperBound = true;
boolean yUpperBound = true;

public Ball()
{
color = new Color(rand.nextFloat(),rand.nextFloat(),rand.nextFloat());
x = rand.nextInt(xLim);
y = rand.nextInt(yLim);
dx = rand.nextInt(9)+1;
dy = rand.nextInt(9)+1;
}

public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
draw(g2);
}

public void draw(Graphics2D g2)
{
ball = new Ellipse2D.Double(x,y,diam,diam);
g2.setColor(color);
g2.fill(ball);
}

public void move()
{
if (((x+dx) < xLim) && xUpperBound)
x+=dx;
else if (x > 0)
{
xUpperBound = false;
x-=dx;
}
else
xUpperBound = true;

if (((y+dy) < yLim) && yUpperBound)
y+=dy;
else if (y > 0)
{
yUpperBound = false;
y-=dy;
}
else
yUpperBound = true;
}

public void animate()
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
try
{
while (true)
{
repaint();
move();
Thread.sleep(40);
}
}
catch (InterruptedException e)
{
System.out.println("Thread was interrupted!");
}
}
});
}
}

BallFrame 类

package BouncingBall;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

public class BallFrame extends JFrame
{
public final static int FRAME_WIDTH = 800;
public final static int FRAME_HEIGHT = 600;

public BallFrame()
{
class ballListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent actionEvent)
{
Thread thread = new Thread()
{
public void run()
{
Ball temp = new Ball();
temp.animate();
add(temp);
}
};
thread.start();
}
}

setLayout(new BorderLayout());
JButton addBall = new JButton("Add Ball");
ActionListener listener = new ballListener();
addBall.addActionListener(listener);
add(addBall, BorderLayout.SOUTH);
}

public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
BallFrame frame = new BallFrame();
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setVisible( true );
}
});
}
}

最佳答案

我在设计中已经遇到的一个问题是,你正在制作 Ball延伸JComponent这已经在很多方面限制了你。你应该只做 Ball一个简单的状态持有者/状态操纵类,具有动画和绘制球状态的方法。

然后只需一个 JComponent/JPanel 类来绘制球。在该类(class)中,您可以有 List<Ball>您将在 paintComponent 中绘制方法。每当你想添加一个球时,只需添加 Ball到列表中。

此外,您应该使用 javax.swing.Timer ,而不是使用单独的线程,这不应该通过绘画来完成(因为所有绘画都应该在 EDT 上完成)。用于计时动画。您可以在How to Use Swing Timers查看更多信息

您还可以看到上述方法的一堆示例 herehereherehereherehere .

<小时/>

更新

"Can you explain extending JComponent limits it? As for not using threads. How would I have multiple Ball objects animate independently? Doesn't that require multiple threads?"

  1. 您必须将多个组件添加到一个可见的“绘画表面”。因此基本上您必须将这些组件分层到表面,必须处理组件不透明度等问题。
  2. 您使用 javax.swing.Timer,在其中循环遍历 List 并调用每个球的 animate() 方法。
  3. 不。

请参阅我发布的链接中的示例。他们有使用计时器和对象列表的示例

这是一些代码片段的基本思想

球类

public class Ball {
public void draw(Graphics g) {}
public void animate() {}
}

BallPanel 类

public class BallPanel extends JPanel {
List<Ball> balls;

public BallPanel() {
Timer timer = new Timer(40, new ActionListener(){
public void actionPerformed(ActionEvent e) {
for (Ball ball : balls) {
ball.animate();
}
repaint();
}
});
timer.start();
}

protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Ball ball : ball ) {
ball.draw(g);
}
}

public void addBall(...) {
balls.add(new Ball(..));
}
}

关于java - 通过 InvokeLater 的多个动画 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23798441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com