Källkoden för /anders.enges/java/blaster.asp
<!--#include file="../inc/navstuff.asp" -->
<H4>Animerade bilder</H4>
<p><a href="./project6/Page1.htm" target="_new">Provkör klassen</a></p>
<p>
<ol>Tema:
<li>Image</li>
<li>MediaTracker</li>
<li>Flertrådiga program</li>
<li>Applet parametrar från HTML sidan</li>
</ol>
</p>
<h4>Trådar (Threads)</h4>
<p>För att få en liten grund till vad trådar är kan du prova följande (om du har NT eller W2K):<p>
<ol>
<li>Starta <b>Task Managern</b> (t.ex gemom att ta Ctrl+Alt+Del)</li>
<li>Välj "fliken" <b>Processes</b></li>
<li>Välj sedan i menyn <b>View, Select Columns...</b> där du kryssar för <b>Thread Count</b>och klickar sedan på <b>OK</b></li>
<li>Bredda vid behov task Managerns fönster.</li>
</ol>
<p>Du kommer i detta fönster att se att många program/processer har en Thread Count som
är större än 1. Detta betyder att dessa program består av flera "delprogram" som körs
pararellt. T.ex. Excel kan lägga igång en omkalkylering av kalkylarket medan en annan del av
programmet kör vidare med sitt. De olikia processerbna i ett program som kan pararellköras
kallas för Threads eller trådar</p>
<p>I VB ser vi aldrig dessa trådar, men i Java kan vi direkt
skapa fler trådar. Om vi t.ex. vill ha ett program som med jämna mellanrum visar en ny bild
måste vi skapa en separat tråd som sköter om dessa byten. I annat fall skulle hela
programmet vara upptaget med bildbytena, och skulle inte kunna göra någonting annat.
<h4>Asynkron laddning och MediaTrackern</h4>
<p>Ett annat inneboende problem med Java (och indirekt Internet) är att saker och ting
inte sker s.k. synkront. Tänk dig t.ex. att du i ett VB program öppnar en fil. Programmet
kommer då att stanna till vid filöppningen, tills filen är helt läst. Sedan fortsätter
programmet.</p>
<p>
I Internet sker motsvarande oftast <b>asynkront</b>. Detta betyder att när vi öppnar en fil
(t.ex. en bildfil), så kommer programmet att fortsätta även om inte filen är helt inläst.
Detta gör att vi efter att ha öppnat en bild inte kan vara helt säkra på att denna bild
är tillgänglig i vårt program. Den kan fortfarande hålla på och laddas...
</p>
<p>På grund av ovastående orsaker är bildhanteringen inte så enkel i Java. Till vår hjälp har vi
dock en klass benämnd MediaTracker, som kan hålla en koll på bilderna och meddela när de är laddade.</p>
<p>Nedanstående program är en direkt variant på den exempelkod som finns för MediaTracker i Javas
hjälp.</p>
<p>För att köra programmet måste vi ha en katalog med namnet <b>images</b> som skall finnas
direkt under den katalog vi har vårt projekt i. Denna katalog skall innehålla en bild med namnet
<b>background.gif</b>, samt 5 st. bildfiler med namnen anim0.jpg, anim1.jpg, anim2.jpg, anim3.jpg samt anim4.jpg</p>
<p>På testsidan finns färdiga bilder du kan använda <a href="./project6/Page1.htm" target="_new">Klicka här</a></p>
<h4>ImageBlaster.java</h4>
<p>Skapa en fil med namnet <b>ImageBlaster.java</b> och sätt in följande kod:
<PRE>
<FONT COLOR="#0000FF">import</FONT> java.applet.Applet<FONT COLOR="#800000">;</FONT>
<FONT COLOR="#0000FF">import</FONT> java.awt.<FONT COLOR="#800000">*</FONT><FONT COLOR="#800000">;</FONT>

<FONT COLOR="#0000FF">public</FONT> <FONT COLOR="#0000FF">class</FONT> ImageBlaster <FONT COLOR="#0000FF">extends</FONT> Applet
     <FONT COLOR="#0000FF">implements</FONT> Runnable <FONT COLOR="#008000">// för att få ett flertrådigt program</FONT>
                         <FONT COLOR="#008000">// har vi Runnable måste vi ha en start, stop och
                         // run funktion i vårt program (se nedan)</FONT>
<FONT COLOR="#800000">{</FONT>
     <FONT COLOR="#008000">// MediaTrackern kan hålla reda på om alla bilder är laddade </FONT>
     MediaTracker tracker<FONT COLOR="#800000">;</FONT>
    
     <FONT COLOR="#008000">// bakgrundsbilden</FONT>
     Image bg<FONT COLOR="#800000">;</FONT>
    
     <FONT COLOR="#008000">// en array med 5 st Images</FONT>
     Image anim<FONT COLOR="#800000">[</FONT><FONT COLOR="#800000">]</FONT> <FONT COLOR="#800000">=</FONT> <FONT COLOR="#0000FF">new</FONT> Image<FONT COLOR="#800000">[</FONT><FONT COLOR="#800080">5</FONT><FONT COLOR="#800000">]</FONT><FONT COLOR="#800000">;</FONT>
    
     <FONT COLOR="#008000">// nuvarande bild</FONT>
     <FONT COLOR="#0000FF">int</FONT> index<FONT COLOR="#800000">;</FONT>
    
     <FONT COLOR="#008000">// en separat tråd som skall sköta om animationen</FONT>
     Thread animator<FONT COLOR="#800000">;</FONT>
    
     <FONT COLOR="#008000">// hämta bilden för bakgrunden (id = 0)</FONT>
     <FONT COLOR="#008000">// och de fem bilderna som skall animeras (id == 1) </FONT>
     <FONT COLOR="#008000">// och lägg in dem i MediaTrackern så att vi vet </FONT>
     <FONT COLOR="#008000">// när de är laddade</FONT>
     <FONT COLOR="#0000FF">public</FONT> <FONT COLOR="#0000FF">void</FONT> init<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT>
     <FONT COLOR="#800000">{</FONT>
         <FONT COLOR="#008000">// skapa en MediaTracker som skall meddela oss </FONT>
         <FONT COLOR="#008000">// när bilderna är laddade</FONT>
         tracker <FONT COLOR="#800000">=</FONT> <FONT COLOR="#0000FF">new</FONT> MediaTracker<FONT COLOR="#800000">(</FONT><FONT COLOR="#0000FF">this</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
        
         <FONT COLOR="#008000">// hämta bakgrundsbilden</FONT>
         <FONT COLOR="#008000">// getDocumentbase() säger var Appletten finns</FONT>
         <FONT COLOR="#008000">// bilderna antas finnas i en images katalog</FONT>
         <FONT COLOR="#008000">// under den katalog som appletten finns i </FONT>
         <FONT COLOR="#008000">// getDocumentBase fungerar inte för en Application</FONT>
         bg <FONT COLOR="#800000">=</FONT> getImage<FONT COLOR="#800000">(</FONT>getDocumentBase<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">,</FONT>
                       <FONT COLOR="#FF0000">"images/background.gif"</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
        
         <FONT COLOR="#008000">// eftersom bilden inte laddas ommeddelbart så</FONT>
         <FONT COLOR="#008000">// säger vi åt vår MediaTracker att den skall meddela oss </FONT>
         <FONT COLOR="#008000">// när den finns tillgänglig</FONT>
         tracker.addImage<FONT COLOR="#800000">(</FONT>bg<FONT COLOR="#800000">,</FONT> <FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
        
         <FONT COLOR="#008000">// hämta resten av bilderna som antas finnas i en images katalog</FONT>
         <FONT COLOR="#008000">// ochhet anim0.gif, anim1.gif ... anim4.gif</FONT>
         <FONT COLOR="#0000FF">for</FONT> <FONT COLOR="#800000">(</FONT><FONT COLOR="#0000FF">int</FONT> i <FONT COLOR="#800000">=</FONT> <FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">;</FONT> i <FONT COLOR="#800000"><</FONT> <FONT COLOR="#800080">5</FONT><FONT COLOR="#800000">;</FONT> i<FONT COLOR="#800000">+</FONT><FONT COLOR="#800000">+</FONT><FONT COLOR="#800000">)</FONT>
         <FONT COLOR="#800000">{</FONT>
             anim<FONT COLOR="#800000">[</FONT>i<FONT COLOR="#800000">]</FONT> <FONT COLOR="#800000">=</FONT> getImage<FONT COLOR="#800000">(</FONT>getDocumentBase<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">,</FONT>
                                <FONT COLOR="#FF0000">"images/anim"</FONT><FONT COLOR="#800000">+</FONT>i<FONT COLOR="#800000">+</FONT><FONT COLOR="#FF0000">".gif"</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
             <FONT COLOR="#008000">// säg åt MediaTrackern at den skall meddela oss när </FONT>
             <FONT COLOR="#008000">// bilderna är tillgängliga</FONT>
             tracker.addImage<FONT COLOR="#800000">(</FONT>anim<FONT COLOR="#800000">[</FONT>i<FONT COLOR="#800000">]</FONT><FONT COLOR="#800000">,</FONT> <FONT COLOR="#800080">1</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
         <FONT COLOR="#800000">}</FONT>
     <FONT COLOR="#800000">}</FONT>
    
     <FONT COLOR="#008000">// start behövs om man har implements Runnable</FONT>
     <FONT COLOR="#008000">// dvs om man har ett flertrådigt program</FONT>
     <FONT COLOR="#0000FF">public</FONT> <FONT COLOR="#0000FF">void</FONT> start<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT>
     <FONT COLOR="#800000">{</FONT>
         <FONT COLOR="#008000">// skap en till tråd och sätt den i animator objektet</FONT>
         animator <FONT COLOR="#800000">=</FONT> <FONT COLOR="#0000FF">new</FONT> Thread<FONT COLOR="#800000">(</FONT><FONT COLOR="#0000FF">this</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
         <FONT COLOR="#008000">// starta denna tråd</FONT>
         animator.start<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
     <FONT COLOR="#800000">}</FONT>
    
     <FONT COLOR="#008000">// stop behövs om man har implements Runnable</FONT>
     <FONT COLOR="#0000FF">public</FONT> <FONT COLOR="#0000FF">void</FONT> stop<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT>
     <FONT COLOR="#800000">{</FONT>
         <FONT COLOR="#008000">// stopp tråden</FONT>
         animator.stop<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
         <FONT COLOR="#008000">// och döda den</FONT>
         animator <FONT COLOR="#800000">=</FONT> <FONT COLOR="#0000FF">null</FONT><FONT COLOR="#800000">;</FONT>
     <FONT COLOR="#800000">}</FONT>
     <FONT COLOR="#008000">// Kör animeringstråden</FONT>
     <FONT COLOR="#008000">// men vänta först på att alla bilder är laddade</FONT>
     <FONT COLOR="#0000FF">public</FONT> <FONT COLOR="#0000FF">void</FONT> run<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT>
     <FONT COLOR="#800000">{</FONT>
         <FONT COLOR="#008000">// felhanteringen i Java fungerar med try - catch systemet</FONT>
         <FONT COLOR="#008000">// som i C++</FONT>
         <FONT COLOR="#008000">// vi försöker således vänta på att bakgrunden är laddad</FONT>
         <FONT COLOR="#008000">// för att sedan vänta på att de övriga bilderna blivit</FONT>
         <FONT COLOR="#008000">// laddade</FONT>
         <FONT COLOR="#0000FF">try</FONT> <FONT COLOR="#800000">{</FONT>
             tracker.waitForID<FONT COLOR="#800000">(</FONT><FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
             tracker.waitForID<FONT COLOR="#800000">(</FONT><FONT COLOR="#800080">1</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
         <FONT COLOR="#800000">}</FONT>
         <FONT COLOR="#008000">// någonting har gått fel - avbryt körningen</FONT>
         <FONT COLOR="#0000FF">catch</FONT> <FONT COLOR="#800000">(</FONT>InterruptedException e<FONT COLOR="#800000">)</FONT>
         <FONT COLOR="#800000">{</FONT>
             <FONT COLOR="#0000FF">return</FONT><FONT COLOR="#800000">;</FONT>
         <FONT COLOR="#800000">}</FONT>
         <FONT COLOR="#008000">// Kolla vilken tråd vi kör</FONT>
         <FONT COLOR="#008000">// och sätt undan denna i en Thread </FONT>
         Thread me <FONT COLOR="#800000">=</FONT> Thread.currentThread<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
        
         <FONT COLOR="#008000">// så länge som den körda tråden är animerings tråden</FONT>
         <FONT COLOR="#0000FF">while</FONT> <FONT COLOR="#800000">(</FONT>animator <FONT COLOR="#800000">=</FONT><FONT COLOR="#800000">=</FONT> me<FONT COLOR="#800000">)</FONT>
         <FONT COLOR="#800000">{</FONT>
             <FONT COLOR="#008000">// försök stoppa tråden 100 millisekunder</FONT>
             <FONT COLOR="#0000FF">try</FONT> <FONT COLOR="#800000">{</FONT>
                 Thread.sleep<FONT COLOR="#800000">(</FONT><FONT COLOR="#800080">1000</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
             <FONT COLOR="#800000">}</FONT>
             <FONT COLOR="#008000">// om det inte gick så avbryter vi loopen</FONT>
             <FONT COLOR="#0000FF">catch</FONT> <FONT COLOR="#800000">(</FONT>InterruptedException e<FONT COLOR="#800000">)</FONT>
             <FONT COLOR="#800000">{</FONT>
                 <FONT COLOR="#0000FF">break</FONT><FONT COLOR="#800000">;</FONT>
             <FONT COLOR="#800000">}</FONT>
            
             <FONT COLOR="#008000">// vi skall öka på index för vilken bild som skall visas</FONT>
             <FONT COLOR="#008000">// för att undvika att någon annan del av programmet</FONT>
             <FONT COLOR="#008000">// försöker göra någonting åt index variabeln så </FONT>
             <FONT COLOR="#008000">// använder vi ordet synchronized, som betyder att </FONT>
             <FONT COLOR="#008000">// denna kod måste bli färdig innan någon annan tråd eller</FONT>
             <FONT COLOR="#008000">// del av programmet får röra index variabeln</FONT>
             synchronized <FONT COLOR="#800000">(</FONT><FONT COLOR="#0000FF">this</FONT><FONT COLOR="#800000">)</FONT>
             <FONT COLOR="#800000">{</FONT>
                 index<FONT COLOR="#800000">+</FONT><FONT COLOR="#800000">+</FONT><FONT COLOR="#800000">;</FONT>
                 <FONT COLOR="#0000FF">if</FONT> <FONT COLOR="#800000">(</FONT>index <FONT COLOR="#800000">></FONT><FONT COLOR="#800000">=</FONT> anim.length<FONT COLOR="#800000">)</FONT>
                 <FONT COLOR="#800000">{</FONT>
                     <FONT COLOR="#008000">// om vi har den sista bilden så tar vi som nästa</FONT>
                     <FONT COLOR="#008000">// den första</FONT>
                     index <FONT COLOR="#800000">=</FONT> <FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">;</FONT>
                 <FONT COLOR="#800000">}</FONT>
             <FONT COLOR="#800000">}</FONT>
             <FONT COLOR="#008000">// rita om Appletten</FONT>
             repaint<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
         <FONT COLOR="#800000">}</FONT>
     <FONT COLOR="#800000">}</FONT>
    
     <FONT COLOR="#008000">// vid uppdatering så ritar vi om allt</FONT>
     <FONT COLOR="#0000FF">public</FONT> <FONT COLOR="#0000FF">void</FONT> update<FONT COLOR="#800000">(</FONT>Graphics g<FONT COLOR="#800000">)</FONT>
     <FONT COLOR="#800000">{</FONT>
         paint<FONT COLOR="#800000">(</FONT>g<FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
     <FONT COLOR="#800000">}</FONT>
     <FONT COLOR="#008000">// Rita en röd bakgrund om bilderna inte kunde hämtas</FONT>
     <FONT COLOR="#008000">// I annat fall så ritar vi dit bakgrundsbilden</FONT>
    
     <FONT COLOR="#0000FF">public</FONT> <FONT COLOR="#0000FF">void</FONT> paint<FONT COLOR="#800000">(</FONT>Graphics g<FONT COLOR="#800000">)</FONT>
     <FONT COLOR="#800000">{</FONT>
         <FONT COLOR="#008000">// har någonting gått fel vid bildhämtningen?</FONT>
         <FONT COLOR="#0000FF">if</FONT> <FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">(</FONT>tracker.statusAll<FONT COLOR="#800000">(</FONT><FONT COLOR="#0000FF">false</FONT><FONT COLOR="#800000">)</FONT> <FONT COLOR="#800000">&</FONT> MediaTracker.ERRORED<FONT COLOR="#800000">)</FONT> <FONT COLOR="#800000">!</FONT><FONT COLOR="#800000">=</FONT> <FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">)</FONT>
         <FONT COLOR="#800000">{</FONT>
             <FONT COLOR="#008000">// röd färg över hela bakgrunden</FONT>
             g.setColor<FONT COLOR="#800000">(</FONT>Color.red<FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
             g.fillRect<FONT COLOR="#800000">(</FONT><FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">,</FONT> <FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">,</FONT> getSize<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT>.width<FONT COLOR="#800000">,</FONT> getSize<FONT COLOR="#800000">(</FONT><FONT COLOR="#800000">)</FONT>.height<FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
             <FONT COLOR="#008000">// och bort härifrån</FONT>
             <FONT COLOR="#0000FF">return</FONT><FONT COLOR="#800000">;</FONT>
         <FONT COLOR="#800000">}</FONT>
         <FONT COLOR="#008000">// kom vi hit borde vi ha en bakgrundsbild som vi </FONT>
         <FONT COLOR="#008000">// då kan rita ut</FONT>
         g.drawImage<FONT COLOR="#800000">(</FONT>bg<FONT COLOR="#800000">,</FONT> <FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">,</FONT> <FONT COLOR="#800080">0</FONT><FONT COLOR="#800000">,</FONT> <FONT COLOR="#0000FF">this</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
        
         <FONT COLOR="#008000">// har vi hunnit ladda alla andra bilder?</FONT>
         <FONT COLOR="#0000FF">if</FONT> <FONT COLOR="#800000">(</FONT>tracker.statusID<FONT COLOR="#800000">(</FONT><FONT COLOR="#800080">1</FONT><FONT COLOR="#800000">,</FONT> <FONT COLOR="#0000FF">false</FONT><FONT COLOR="#800000">)</FONT> <FONT COLOR="#800000">=</FONT><FONT COLOR="#800000">=</FONT> MediaTracker.COMPLETE<FONT COLOR="#800000">)</FONT>
         <FONT COLOR="#800000">{</FONT>
             <FONT COLOR="#008000">// om så är fallet så kan vi rita ut den som </FONT>
             <FONT COLOR="#008000">// är aktuell. Om index är 1 kommer således</FONT>
             <FONT COLOR="#008000">// anim1.gif att ritas</FONT>
             g.drawImage<FONT COLOR="#800000">(</FONT>anim<FONT COLOR="#800000">[</FONT>index<FONT COLOR="#800000">]</FONT><FONT COLOR="#800000">,</FONT> <FONT COLOR="#800080">10</FONT><FONT COLOR="#800000">,</FONT> <FONT COLOR="#800080">10</FONT><FONT COLOR="#800000">,</FONT> <FONT COLOR="#0000FF">this</FONT><FONT COLOR="#800000">)</FONT><FONT COLOR="#800000">;</FONT>
         <FONT COLOR="#800000">}</FONT>
     <FONT COLOR="#800000">}</FONT>
<FONT COLOR="#800000">}</FONT>
 
</PRE>
</p>
<!--#include file="../inc/footer.asp" -->