# Animation in Canvas (Rückstände)



## Marcel_Handball (3. Feb 2007)

Hallo zusammen,
ich versuche gerade ein Applet zu programmieren, in der eine Animation, mit Hilfe der Thread-Klasse, in einem Canvas von oben nach unten "laufen" soll. 

Ich hab dazu einfach mal eine "Line" verwendet, die waagerecht liegt, und dessen y-Werte sich per Schleife nach unten bewegen.
Das Problem, dass ich nun habe, ist, dass daraus ein Rechteck wird, da die Linien mit den "älteren" y-Koordinaten nicht wieder verschwindet. ( Es wurden somit viele Linien einfach untereinander gemalt).

Aber es soll sich nur eine Linie bewegen und *keine Rückstände hinterlassen*.
Hier, was ich bisher geschrieben habe.


```
import java.applet.*;
import java.awt.*;
import java.awt.event.*; 

public class ani extends Applet implements Runnable
{   Thread myThread;
    Canvas zeichenfeld=new Canvas();
    Button halt=new Button("Anhalten");
    boolean lauf=true;
    int weite=5;
    
    public void init(){
        
        setLayout(null);
        zeichenfeld.setBackground(Color.black);
        zeichenfeld.setBounds(10,10,300,300);
        add(zeichenfeld);
        
        halt.setBackground(Color.gray);
        halt.setBounds(320,10,100,25);
        add(halt);
        
        ereignisbehandlung( );
  
    }

    public void start(){
        if(myThread==null){myThread=new Thread(this); 
        myThread.start();}
    }
    
    public void run(){
        Graphics g;
        g= zeichenfeld.getGraphics( );
        while(myThread != null){
        
        for(int a=weite;a<=295; a++){
        
            g.setColor(Color.red);
            g.drawLine(5,a,200,a);
            weite=a;
            try{myThread.sleep(20);}catch(InterruptedException e){}
        }}
    }
    
    public void stop(){
        myThread.stop();
        myThread = null;
    }

    
  public void ereignisbehandlung( ) {
    halt.addActionListener( new ActionListener( ) {
      public void actionPerformed( ActionEvent e ) {
          if(lauf==true){stop(); lauf=false;}
            else{start(); lauf=true;}
      }
    } ); 
   }

}
```

Was muss ich verändern, um dies hinzukriegen? 

Schon im Voraus vielen Dank für eure Hilfe.


----------



## Marco13 (3. Feb 2007)

Es gibt "fast nie" einen Grund, "getGraphics" aufzurufen

Lies dir mal 
http://java.sun.com/products/jfc/tsc/articles/painting/
durch. Das entscheidende ist, dass alles, was gemalt wird, immer in der paint-Methode gemalt werden muss. 

Am einfachsten erreicht man das, indem man eine Klasse von Canvas ableitet, und die paint-Methode so überschreibt, dass dort die _aktuelle_ Linie an der richtigen Position gezeichnet wird.

Wenn du dort vorher dann den Hintergrund clearen willst, kannst du das durch

```
g.setColor(Color.WHITE);
    g.fillRect(0,0,getWidth(),getHeight());
```
erreichen. (Aber bitte diese Zeilen jetzt NICHT einfach so ein dein Porgramm einbauen (was zwar funktionieren würde, aber "falsch" wäre))

EDIT:
Ich sehe gerade, dass du Thread.start/stop verwendest. Die sind deprecated. Wie man das "richtig" macht, steht hier
http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
Wenn daran was unklar ist, einfach nochmal nachfragen


----------



## Marcel_Handball (3. Feb 2007)

Erst einmal vielen Dank für deine Antwort !!!

Ich hab jetzt erst einmal versucht das stop-"Problem" zu verbessert:


```
public void start(){
        if(myThread==null){myThread=new Thread(this); 
        myThread.start();}
    }
    
    public void run(){
        thisThread = Thread.currentThread();
        Graphics g;
        g= zeichenfeld.getGraphics( );
        while(myThread == thisThread){
        
        for(int a=weite;a<=295; a++){
        
            g.setColor(Color.red);
            g.drawLine(5,a,200,a);
            weite=a;
            try{thisThread.sleep(20);}catch(InterruptedException e){}
        }}
    }
    
    public void stop(){
        myThread = null;
    }
```

Leider hält aber mit dieser Methode das Thread nicht mehr an, was mache ich falsch?

Marcel


----------



## Marcel_Handball (3. Feb 2007)

EDIT 

... gibt es denn keine andere Möglichkeit in einem Canvas eine Animation darzustellen, als mit "ClearRect()" bzw. "FillRect()", sodass keine Rückstände zurückbleiben.

Und wie kann ich die Paint Methode dazu verwenden in das Canvas zu zeichnen ohne "getGraphics()"? Hab noch nicht allzuviel Erfahrung, deshalt muss ich so blöd fragen.

Danke für eure Antworten.


----------



## Marcel_Handball (3. Feb 2007)

Danke nochmal für den Link, habe das stop-Problem gelöst. Lag an der For-Schleife die immer zuende geführt wurde.


----------



## Marco13 (3. Feb 2007)

Für das Zeichnen der Animation mußt/solltest du eine Klasse von Canvas ableiten. UNGEFÄHR(!) so (was genau die "beste" Lösung ist, muß sich derjenige überlegen, der weiß, was dabei am Ende rauskommen soll)


```
class MyAnimationCanvas extends Canvas
{
    int x0, y0, x1, y1; // Endpunkte der aktuellen Linie, werden über eine set-Methode gesetzt

    public void paint(Graphics g)
    {
        g.setColor(Color.WHITE);
        g.fillRect(0,0,getWidth(),getHeight());
        g.drawLine(x0,y0,x1,y1); // Aktuelle Linie zeichnen
    }
}

....

    for (...)
    {
        myAnimationCanvas.setLineEndpoints(x0,y0,x1,y1); // Aktuelle Linie setzen
        myAnimationCanvas.repaint();
    }
```
(Das soll nur das Prinzip verdeutlichen!)


----------

