gpt4 book ai didi

java - 使用 JFrame 和 JPanel 的简单 Java 动画

转载 作者:行者123 更新时间:2023-11-29 03:14:28 26 4
gpt4 key购买 nike

好的,所以该程序的目的只是绘制椭圆形并将其移动到屏幕上。代码在 Eclipse 上编译没有错误,但在运行时,没有在屏幕上绘制或移动椭圆。我一直在研究,似乎线程必须为此做很多事情,但是这个简单的程序需要一个吗?我显然是使用 Swing 进行 GUI 编程的新手,因此对于有关线程或此类相关概念的程序的任何补充,我将不胜感激。

public class Game extends JPanel
{
int x =0;
int y =0;

private void moveBall()
{

x+=1;
y+=1;
}

public void paint (Graphics g)
{
super.paint(g);
g.fillOval(x, y, 30, 30);
}

public static void main(String[] args) {
JFrame frame = new JFrame("Animation");
Game game = new Game();
frame.add(game);
frame.setVisible(true);
frame.setSize(300,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
while (true)
{
game.moveBall();
game.repaint();

}
}
}

最佳答案

可能的问题是,该线程对于 UI 来说运行得太快,在“球”离开可见区域后 UI 显示得很好。

你需要做几件事......

首先,您需要确保在事件调度线程中正确安排更新,其次,更新之间有一个短暂的延迟。例如,25fps 大约是更新之间的 40 毫秒延迟,60fps 大约是 16 毫秒

有很多方法可以实现这一点,具体取决于您希望实现什么,例如,您可以简单地使用 Thread.sleep 使线程暂停一小段时间更新之间的时间。这样做的问题是 Swing 不是线程安全的,所有对 UI 的更新都应该在事件调度线程的上下文中进行。

虽然您的程序只是简单的,但有可能在您更新状态时运行绘制循环,从而导致脏更新。

另一个解决方案可能是使用 Swing Timer,它允许您定期安排更新,这些更新在事件调度线程的上下文中触发,使其使用起来更安全。

看看Concurrency in SwingHow to use Swing Timers了解更多详情。

举个例子...

Moving Ball

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BallAnimation {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new BallAnimation();
}

public BallAnimation() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private int x = 0;
private int y = 0;

public TestPane() {
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
moveBall();
repaint();
}
});
timer.start();
}

protected void moveBall() {
x++;
y++;
}

@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.fillOval(x, y, 30, 30);
g2d.dispose();
}

}

}

作为旁注,除非你真的有理由这样做,否则你应该避免覆盖 paint 而是使用 paintComponent

关于java - 使用 JFrame 和 JPanel 的简单 Java 动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27475048/

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