问题
I am trying to move a ball in applet using thread but its not moving. Can anyone help me out as m new to applet and proceeding for game development..for reference here is my code
public class ballGame extends JApplet implements Runnable
{
int x_pos=50;
int y_pos=100;
int rad=10;
Thread t;
public void start()
{
super.start();
t=new Thread("t");
t.start();
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.red);
setBackground(Color.BLACK);
g.drawOval(x_pos,y_pos,2*rad,2*rad);
while(true)
{
x_pos++;
//validate();
repaint();
try
{
Thread.sleep(100);
}
catch(Exception e)
{
e.printStackTrace();
}
}//end of while
}//end of paint()
}
回答1:
Swing is a single thread environment. That is, all updates and interactions are executed within a single thread. Swing is also NOT thread safe. This means that all updates to the UI MUST be executed within the context of that thread (the Event Dispatching Thread or ETD).
Any code that blocks the EDT will prevent it from (amongst other things), repainting the UI and responding to input from the user.
You're paint code will NEVER update the screen, in fact it will make your application appear to "hang", as the paint
method isn't being allowed to complete and is blocking the ETD.
It is an exception that the paint
method will return quickly after been called and may be called repeatedly in quick succession.
Generally speaking, a Thread
is probably a little over kill, something like a javax.swing.Timer
would be more then suitable under these circumstances.

public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}
As a side note. You should rarely need to override the paint
method of a top level container like JApplet
or JFrame
, while there are a number of good reasons for this, the one that you're going to most interested in is the fact that they're not double buffered, meaning you are likely to see flickering as the screen is updated.
It's better to use something like JPanel
and override it's paintComponent
method instead.
Take a look at
- Performing Custom Painting
- Concurrency in Swing
- Painting in AWT and Swing
For more information
nb
While I've used a JFrame
for my example, it would be a simple matter to take the animation panel and put it into a JApplet
, this is another reasons why you don't need/want to extend from top level containers ;)
回答2:
Having an infinite loop in paint
means that not a single pass of the method can complete.
Also you should never call Thread.sleep(100)
in the paint
method. This blocks the EDT
and degrades performance.
Instead use a Swing Timer to do the update and repainting work. Also I would sub-class a JComponent
and override paintComponent
.
回答3:
You can not invoke repaint() method inside paint(). And you can not organize infinitely loop inside paint() method - doing so, you are blocking drawing in your applet.
回答4:
x_pos
is an int value, thus it is passed to methods by value, not by reference. That is why, when you change its value, the value inside of your circle is not updated...
回答5:
You create a Thread without a run()
method. This method should contain the runnable code... Furthermore, the paint()
method is to paint stuff, not update stuff!
So move your while loop from the paint()
method into the run()
method of your thread:
t=new Thread("t") {
@Override
public void run()
{
while(true)
{
x_pos++;
//validate();
repaint();
try
{
Thread.sleep(100);
}
catch(Exception e)
{
e.printStackTrace();
}
}//end of while
}
};
Note that ballGame
does not require the implement Runnable
part. As the thread you created will provide it.
回答6:
Have the while loop inside the run method of Runnable.
UPDATE:
Have this in the start method.
t=new Thread(this);
t.start();
来源:https://stackoverflow.com/questions/14456072/i-am-trying-to-move-a-ball-in-applet-using-thread-but-its-not-moving