Do not draw on or access GUI components from the main thread (or any other thread for that matter). You can only safely render components from Swing's EDT. With the way your program is structured right now (your loop on the main thread constantly directly repainting the component), all bets are off. You should use the infrastructure that Swing provides you; in particular, render in paint()
and trigger updates properly via repaint()
.
I suggest you move your drawing code into the component's paint(Graphics)
, then either drive game logic on a timer or keep it in the main thread, and use repaint()
to trigger redraws (it can be called from any thread, and will cause paint()
to happen on the EDT).
Also, when you initially create your frame, do it on the EDT via e.g. SwingUtilities.invokeAndWait()
From http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html:
Programs that ignore this rule may function correctly most of the time, but are subject to unpredictable errors that are difficult to reproduce.
Have a read of the official tutorial on concurrency in Swing. It will give you a good starting point.