Phil Freihofner wrote:Lots of improvements in the code!
The "normal" way to do graphics is to override paintComponent(Graphics g). Then, in the game loop call repaint(). When this is done, the redrawing is placed on the EDT (event dispatch thread) and handled in an orderly fashion.
I don't know enough about the internals of Java to say why what you are doing does not work consistently. It could be that the drawing events you are attempting are getting "collapsed". Sometimes Java decides that two events on the EDT are similar enough that the second one is sufficient and it ignores the first. However, this can lead to situations where new events keep coming in and nothing ever gets displayed.
I've had this happen when the JPanel calls its own repaint via a Timer. When I put the Timer in a separate Object, and had that call the JPanel's repaint(), the collapsing stopped occurring. A similar thing could happen with a game loop residing on the very JPanel that is to be redisplayed. Placing your game loop in a separate object might be needed. (I've always used the Timer, not a game loop, so I can't say for sure.)
There are also many other mysteries (to me) as to how Swing and AWT schedule events. So I recommend, as a start, go with the normal method (using repaint() for displaying a JPanel, in conjunction with using paintComponent(Graphics g) and the Graphics object it provides) and see if the problem persists.