Applet d'animation Java avec MediaTracker, threads et timer
J'ai 3 questions sur mon projet d'animation.
- La structure du programme est-elle correcte (voir ci-dessous)
- Ma première image (d'un tableau) ne se comporte pas correctement. Parfois, il apparaît puis disparaît, puis le reste des images s'affichent correctement.
- Comment puis-je contrôler quand le clip audio commence à jouer. On dirait aussi parfois qu'une aiguille déchire un disque...?
CONCERNANT LA STRUCTURE DU PROGRAMME: Sont les suivants dans le bon ordre:
DANS INIT:
- Définir la taille de l'applet.
- Exécuter une tâche de minuterie avec un temps de sommeil
- Obtenez le fichier son.
- Récupère les images du tableau.
- Initialisez l'objet MediaTracker et dites-lui d'attendre toutes les images.
- Lire le fichier son.
AU DÉBUT(Graphique g) 1. Dessinez l'applet et chargez la première image du tableau
AU DÉBUT: 1. Vérifier les fils pour les valeurs null, sinon null, commencez
EN COURS D'EXÉCUTION: 1. Utilisez une variable "iPictureNumber" pour parcourir les images dans un ordre séquentiel en utilisant également repaint et Thread.méthodes de sommeil
DANS LA MISE À JOUR: 1. Dessiner l'appliquette.
Ce code est une version mise à jour d'un autre programme que j'ai qui n'a pas utilisé de threads, donc je ne sais pas si c'est la bonne structure. Mon objectif est d'utiliser les meilleures pratiques avec ce type de programme simple. Je peux fournir les images et le son dans un fichier zip si nécessaire. Veuillez conseiller, merci d'avance. VOICI LE CODE:
// Projet d'animation Java avec tableau d'images et 1 fichier son utilisant des threads
import java.net.*;
import java.io.*;
import java.lang.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.applet.Applet;
import java.applet.AudioClip;
import java.util.*;
public class c_TrainAnimation extends Applet implements Runnable
{
Image trainAndBush[];
int totalImages = 17,
currentImage = 0, // Set current image array subscript to 0
sleepTime = 900;
Image imageCurrent; // Set to the matching image in "trainAndBush" Array
MediaTracker myImageTracker;
Timer myTimer;
Thread threadTrainAnimation = new Thread(this);
Thread threadSoundFile = new Thread(this);
AudioClip mySound;
public void init()
{
setSize(400,400);
myTimer = new Timer(true);
myTimer.schedule( new TimerTask()
{
public void run()
{ repaint();}
} // end TimerTask
,0,sleepTime);
mySound = getAudioClip(getDocumentBase(), "onpoint.au");
trainAndBush = new Image[ totalImages ];
// Load the array of images into the Applet when it begins executing
for( int i = 0; i < trainAndBush.length; i++ )
{
trainAndBush[i] = getImage(getDocumentBase(),
"Hill" + (i + 1) + ".jpg" );
myImageTracker = new MediaTracker( this );
// Give the images an ID number to pass to MediaTracker
myImageTracker.addImage(trainAndBush[i], i);
// Tell MediaTracker to wait until all images are loaded
try
{
myImageTracker.waitForAll();
}
catch(Exception e) {}
mySound.play();
} // end for loop
} // end init
// check threads for null values and then start threads
public void start()
{
if (threadTrainAnimation != null )
threadTrainAnimation.start();
if (threadSoundFile != null )
threadSoundFile.start();
}
// Draw the applet with the first image of the array
public void start(Graphics g)
{
g.drawImage(trainAndBush[0],50,50,300,300, this );
currentImage = 0;
}
// Set "imageCurrent"to appropriate "trainAndBush image" in the array and_
loop through
public void run()
{
int iPictureNumber[] = {0, 1, 2, 3,4,5,6,7,8,9,10,11,12,13,14,15,16};
while( true )
{
for( int i = 0; i < iPictureNumber.length; i++ )
{
imageCurrent = trainAndBush[iPictureNumber[i]];
repaint();
try
{
Thread.sleep( sleepTime );
}
catch( InterruptedException e) {}
} // end for loop
} // end while statement
} // end run
public void update(Graphics g)
{
g.drawImage( imageCurrent, 50, 50, 300, 300, this );
}
} // end of Applet
1 answers
Je n'utiliserais pas Applet
, utilisez JApplet
, cela résoudra des dizaines de problèmes dès le départ ;)
J'utiliserais probablement des Runnables
séparés pour les threadTrainAnimation
et threadSoundFile
, mais je n'ai pas eu beaucoup d'expérience avec le son dans le passé. Le problème que je vois cependant est que vous avez deux threads qui accèdent simultanément à la partie de code en faisant la même chose. C'est juste faire un gâchis de choses.
Vous devez comprendre comment synchroniser le son et l'animation.
L'utilisation du java.util.Timer
est incorrect pour ce que vous essayez de réaliser, c'est aussi exagéré étant donné que vous avez threadTrainAnimation
en cours d'exécution, car ils font généralement la même chose. Dans ce cas, je m'en débarrasserais probablement. À l'avenir, il est préférable d'utiliser javax.swing.Timer
car il fournit un meilleur support pour le Event Dispatching Thread
Personnellement, je ne chargerais pas mes ressources dans la méthode init
comme vous êtes. Cela va ralentir le chargement de l'applet et contrarier les utilisateurs. Vous feriez mieux de mettre en place une belle "chargement" de l'image et utiliser un Thread
pour effectuer le chargement. Une fois cela fait, en utilisant quelque chose comme SwingUtilities.invokeLater
pour démarrer l'animation.
Ne remplacez pas la méthode update
, vous devriez remplacer la méthode paint
à la place.
Il est également possible que les images soient modifiées plus rapidement puis qu'elles puissent être peintes, vous voudrez peut - être y réfléchir également-c'est-à-dire que la méthode run
peut s'exécuter plusieurs fois avant que paint
ne soit appelé
Comme suggestion, j'avais lu par
- la Simultanéité dans Swing
- Effectuer une Peinture personnalisée
- Peinture en AWT et Swing
- Comment faire des Applets (lorsqu'ils discutent de l'animation ici)
Si vous êtes sérieux au sujet de l'animation, je vérifierais aussi
- TimingFramework et/ou
- Trident
Qui sont des frameworks d'animation pour Java