我正在尝试创建一个程序,该程序将绘制 2 个球,一个在北中心,另一个在南中心。我需要将球向不同方向移动,北方的第一个球随机向南移动,而南方中心的另一个球向北移动。我可以让北中心的球向下移动,但南边的第二个球在被抽出后立即消失。
PS:我需要有 2 个内部类,即Ball1
和Ball2
. 请帮忙。非常感谢。
我正在尝试创建一个程序,该程序将绘制 2 个球,一个在北中心,另一个在南中心。我需要将球向不同方向移动,北方的第一个球随机向南移动,而南方中心的另一个球向北移动。我可以让北中心的球向下移动,但南边的第二个球在被抽出后立即消失。
PS:我需要有 2 个内部类,即Ball1
和Ball2
. 请帮忙。非常感谢。
问题...
while-loop
在调整图形对象位置的事件调度线程中Thread.sleep
在paint
方法中。super.paintComponent
paintComponent
。Swing 使用单线程模型,除其他外,该模型负责将重绘请求分派给所有组件。
在 EDT 中执行任何停止处理这些事件的操作都会阻止 Swing 重新绘制 UI。这将使您的动画看起来像是突然从头到尾一步到位。
查看Swing 中的并发以获取更多详细信息。特别是,看看Initial Threads和How to use Swing Timers
我应该强调第4点-
您无法控制重绘周期。重绘请求可能会因多种原因而被提出,您没有要求,这些将导致您的对象更新超出您的控制或当您不希望它们更新时。paint
你永远不应该在任何方法中更改 UI 任何部分的状态。
简单示例
这是一个非常简单的示例,但它演示了在 Swing 中制作任何动画所需了解的基本概念
public class SimpleBouncyBall {
public static void main(String[] args) {
new SimpleBouncyBall();
}
public SimpleBouncyBall() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CourtPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CourtPane extends JPanel {
private Ball ball;
private int speed = 5;
public CourtPane() {
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Rectangle bounds = new Rectangle(new Point(0, 0), getSize());
if (ball == null) {
ball = new Ball(bounds);
}
speed = ball.move(speed, bounds);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (ball != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Point p = ball.getPoint();
g2d.translate(p.x, p.y);
ball.paint(g2d);
g2d.dispose();
}
}
}
public class Ball {
private Point p;
private int radius = 12;
public Ball(Rectangle bounds) {
p = new Point();
p.x = 0;
p.y = bounds.y + (bounds.height - radius) / 2;
}
public Point getPoint() {
return p;
}
public int move(int speed, Rectangle bounds) {
p.x += speed;
if (p.x + radius >= (bounds.x + bounds.width)) {
speed *= -1;
p.x = ((bounds.x + bounds.width) - radius) + speed;
} else if (p.x <= bounds.x) {
speed *= -1;
p.x = bounds.x + speed;
}
p.y = bounds.y + (bounds.height - radius) / 2;
return speed;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
g.fillOval(0, 0, radius, radius);
}
}
}