At first I did this:
public SpaceCanvas(){
new Thread(new Runnable () {//this is the thread that triggers updates, no kidding
int fcount = 0;
@Override
public void run() {
System.out.println("Update thread started!");
while(!Thread.interrupted()){
fcount++;
while(players.iterator().hasNext()){
players.iterator().next().update(fcount);
}
while(entities.iterator().hasNext()){
entities.iterator().next().update(fcount);
}
System.out.println("About to paint");
repaint();
System.out.println("Done with paints");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
players.add(new LocalPlayer(0, 9001, 0, 0, 0, 0, this, null));
}
in the initializer of a thing I call a SpaceCanvas. However, that doesn't allow the canvas, and therefore the applet it is within, to be created, because the Thread doesn't actually run asynchronously. Then, I replaced ".start()" with ".run()" and the thread only ran once, but the SpaceCanvas initialized perfectly.
What did I do wrong, and how do I fix this?
I'm not sure this sort of code works the way you expect it to:
while(players.iterator().hasNext()){
players.iterator().next().update(fcount);
players.iterator()
gets a new iterator for the players
collection. If there are 0 items in the collection then it will be false
but if there are any items, you will be in an infinite loop, creating a new iterator each time. The iterator()
call inside of players
generates another new iterator object as well.
I think you should doing something like:
Iterator iterator = players.iterator();
while (iterator.hasNext()) {
iterator.next().update(fcount);
}
This is the same with your entities
loop as well. A better pattern (as of Java 5) is to use the for
loop:
for (Player player : players) {
player.update(fcount);
}
Also, if multiple threads are accessing these collections, they have to be somehow synchronized
. You can either use a concurrent collection or you have to make sure every access (read and write) is within a synchronized
block.
synchronized (players) {
for (Player player : players) {
player.update(fcount);
}
}
...
// down in the outer thread
synchronized (players) {
players.add(new LocalPlayer(0, 9001, 0, 0, 0, 0, this, null));
}
Obviously the entities
will need to be synchronized
in the same manner.
JApplet/JPanel
) rather than AWT ( Applet/Canvas
) Timer
that calls repaint()
every 500 msec. Timer
) Don't call Thread.sleep(n)
on the EDT (Event Dispatch Thread). ..can you draw on a JPanel?
Sure thing. To do so, override the paintComponent(Graphics)
method. You might also extend a JComponent
and do the same, but there are some quirks to dealing with a JComponent
that make the JPanel
the better choice to extend.
On the other hand, there is another approach entirely.
BufferedImage
of the size required for whatever custom graphic is needed. ImageIcon
. JLabel
. Timer
action.
image.getGraphics()
to obtain the drawing surface. paint()
or paintComponent()
dispose()
of the Graphics
instance of the image. label.repaint()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.