【发布时间】:2014-04-20 12:23:43
【问题描述】:
我正在制作一个简单的“弹跳球”——Java 动画。这个想法是,它最初会生成一个沿直线移动的球,直到撞到面板边框,这会导致它像您预期的那样反弹。然后,您可以通过鼠标单击在 x,y 位置生成额外的球。到目前为止,一切都很好。
我的问题是每个球都启动自己的线程,每个线程以自己的间隔单独拉入面板,导致面板疯狂闪烁。我知道可以通过实施双缓冲来解决此类问题,我已经阅读过,但我自己从未完全使用过。
我想知道如何在这里使用双缓冲,如果同时绘制多个线程可能是一个问题(或者相反,甚至是常态)?
提前非常感谢!
代码如下:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
class MyCanvas extends JPanel
{
MyCanvas()
{
setBackground(Color.white);
setForeground(Color.black);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
public Dimension getMinimumSize()
{
return new Dimension(300,300);
}
public Dimension getPreferredSize()
{
return getMinimumSize();
}
}
public class BouncingBalls extends JFrame // main class
{
MyCanvas m_gamefield;
public BouncingBalls()
{
setLayout(new BorderLayout());
m_gamefield = new MyCanvas();
add("Center",m_gamefield);
m_gamefield.addMouseListener(new MeinMausAdapter());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public void letsgo()
{
Ball first = new Ball(m_gamefield,200,50);
first.start();
}
class MeinMausAdapter extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
Ball next = new Ball(m_gamefield,e.getX(),e.getY());
next.start();
}
}
public static void main(String[] args)
{
BouncingBalls test = new BouncingBalls();
test.setVisible(true);
test.pack();
test.letsgo();
}
}
class Ball extends Thread
{
JPanel m_display;
int m_xPos,m_yPos;
int m_dx = 2; // Steps into direction x or y
int m_dy = 2;
Ball(JPanel c,int x,int y)
{
m_display = c;
m_xPos = x;
m_yPos = y;
}
public void run()
{
paintBall(); // Paint at starting position
while(isInterrupted() == false)
{
moveBall();
try
{
sleep(20);
}
catch(InterruptedException e)
{
return;
}
}
}
void paintBall()
{
Graphics g = m_display.getGraphics();
g.fillOval(m_xPos, m_yPos, 20, 20);
g.dispose();
}
void moveBall()
{
int xNew, yNew;
Dimension m;
Graphics g;
g = m_display.getGraphics();
m = m_display.getSize();
xNew = m_xPos + m_dx;
yNew = m_yPos + m_dy;
// Collision detection with borders, "bouncing off":
if(xNew < 0)
{
xNew = 0;
m_dx = -m_dx;
}
if(xNew + 20 >= m.width)
{
xNew = m.width - 20;
m_dx = -m_dx;
}
if(yNew < 0)
{
yNew = 0;
m_dy = -m_dy;
}
if(yNew + 20 >= m.height)
{
yNew = m.height - 20;
m_dy = -m_dy;
}
g.setColor(m_display.getBackground()); // Erases last position by
g.fillRect(m_xPos-2, m_yPos-2, m_xPos+22, m_yPos+22); // painting over it in white
m_xPos = xNew;
m_yPos = yNew;
paintBall(); // paint new position of Ball
g.dispose();
}
}
【问题讨论】:
-
任何通过在
Component上调用getGraphics()完成的绘画迟早会以一种或另一种形式中断。这根本不是您在 AWT/Swing 中绘制的方式。你应该阅读docs.oracle.com/javase/tutorial/uiswing/painting。除此之外:每个球一个线程完全是矫枉过正。一个线程可以处理 1000 个球。也许你应该解释你想用这些线程实现什么。他们不会在这里带来任何优势。如果你有,也许,100000 个球,并且想用 10 个线程来做 运动,好的。但是绘画仍然是由一个线程完成的。
标签: java multithreading animation double buffering