2016-04-03 1 views
1

J'ai une animation dans un JPanel qui se met à jour via un javax.swing.Timer. Ce temporisateur peut être construit pour avoir un délai en millisecondes qui doit être un entier. Si je devais avoir la mise à jour de JPanel 60 fois chaque seconde, je fixerais le retard à 1000/60 = ~ 16.6666. Cependant, ce délai doit être un int, j'ai donc la possibilité d'arrondir à la hausse ou à la baisse. Pour un délai de 16 millisecondes, l'animation serait mise à jour à 62,5 images par seconde. Arrondir à un retard de 17 millisecondes donnerait un taux de trame de 58.824.Java Timer Swing Exactement 60 fps

Comment procéder pour avoir une fréquence d'images de 60 images par seconde exactement?

Merci d'avance.

+1

La minuterie du système a typiquement une résolution de ~ 15ms. Il est donc peu probable que vous ayez la résolution précise que vous souhaitez. –

+1

Même si la minuterie du système est inexacte, il convient de faire la moyenne des erreurs dans le temps (si ma logique n'est pas fausse) et de toujours donner les mêmes fréquences d'images non désirées (ci-dessus). – olta8

Répondre

1

Je vois deux options qui pourraient vous aider. En fin de compte, ils réalisent la même chose de la même façon, mais le code est plus ou moins général. Je n'ai trouvé aucun outil qui fasse le travail pour vous, donc cela demande un peu de travail.

La première option est de faire quelque chose comme ceci:

/** 
* Called by the timer when the next iteration is due. Assume that 
* this happens at the right moment. 
*/ 
public void onTimerUpdate() { 
    updateAnimation(); 

    // Compute the next point in time that corresponds to the 
    // frame rate you want. 
    long nextScheduledTimestamp = getNextTimestampInNanos(); 

    long nanos = System.timeNanos(); 
    timer.schedule(task, convertToMillis(nextScheduledTimestamp - nanos)); 
} 

La deuxième option est pour vous d'obtenir votre copie de java.util.Timer: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Timer.java

et réécrire les bits qui sont milliseconde spécifique. Rien dans sa mise en œuvre OpenJDK montre que sa résolution est milliseconde spécifique, donc vous devriez être en mesure de remplacer Object.wait(millis) appels avec Object.wait(millis, nanos): https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long,%20int)

article intéressant, juste pour le plaisir: https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks

0

Il est loin d'être aussi compliqué que cette! Vous pouvez facilement accomplir repeindre() ou toute autre méthode que vous devez appeler exactement 60 fois par seconde avec la boucle plus simple dans l'existence

while(true) { 
    repaint(); 
    try { 
     Thread.sleep(1000/60); 
    } catch (InterruptedException e) { 
    } 
} 

Je l'appelle dans la principale méthode de mon script, mais fondamentalement, il est une boucle infinie puisque le vrai sera toujours vrai, alors il appelle repeindre, dit à la boucle de dormir pour une image, puis appelle repeindre. Et le sommeil 1000/60 entraînera l'appel de cette boucle exactement 60 fois par seconde