I generally use system time to keep a steady ‘loop rate’ (game speed) and then have the repaint method called after the main loop, but only if the main loop is keeping up to speed.
eg.
I generally have gameSpeed set to 30 (30 loops a second).
If the system is running to slow, it’s set up to skip rendering to keep the loop rate constant (so if the game runs badly, all characters etc move at the same speed).
This is achieved by performing the main loop if the time through the current second (the millisecond) is up to the current loop time, which is incremented by 1000 / gameSpeed per loop.
It then checks if the loop rate is keeping up by checking if there have been enough loops this second according to the current millisecond. If there has, rendering takes place.
This also allows the frame rate and loop rate to be easily recorded, by having a fpsCounter that is incremented for each repaint call, and a lpsCounter incremented per loop.
Then just display them at the end of each second.
One thing that does confuse me is programs returning frame rates to decimal points - did it only half finish the rendering for the final frame?