Thread mit Bildern

wmgame

Grünschnabel
Ich habe ein kleines Lokomotivenrennen in Java programmiert. Dazu habe ich Threads verwendet. Bisher habe ich die Lokomotive mit Rechtecken und anderen Formen gemalt und asgefüllt. Jetzt möchte ich aber doch etwas komplexere Dinge als eine Lokomotive nehmen, deshalb möchte ich den Gegenstand nicht mehr malen, sondern ich möchte ein Bild (Image) verwenden. Jedoch funktioniert das nicht so einfach. Habt ihr eine Idee wie ich das lösen kann?

Hier mein Quelltext:

Klasse Lok:

Code:
 import java.awt.*;

 class Lok implements Runnable{
 

  // Anfang Attribute
    private int posx,posy;
    private Graphics g;
    private Panel p;
  // Ende Attribute


     Lok (int x, int y, Graphics param_g, Panel param_p){
      posx=x;
      posy=y;
      g= param_g;
      p= param_p;
     }

  // Anfang Methoden

     void malelok(Graphics g){
     
      int[] xwerte={posx+0,posx+30,posx+30,posx+60,posx+60,posx+70,posx+70,posx+0,posx+0};
      int[] ywerte={posy+0,posy+0, posy+20,posy+20,posy+0, posy+ 0,posy+40,posy+40,posy+0 };
      
      g.setColor(Color.black);
      g.fillPolygon(xwerte, ywerte,xwerte.length);
      g.setColor(Color.red);
      g.drawOval(posx+10,posy+30,20,20);
      g.drawOval(posx+40,posy+30,20,20);
      g.setColor(Color.green);
      g.fillOval(posx+10,posy+30,20,20);
      g.fillOval(posx+40,posy+30,20,20);
     }
     public void setposx(int x){
       posx= x;
     }
     public void run(){


       for (int i=1; i<100;i=i+10){
         malelok(g);
         pause();
         dampfe(g);
         g.setColor(p.getBackground());
         // altes Lokbild übermalen:
         //p.repaint();  VARINTE I geht nicht ********
         // p.setBackground(Color.cyan); VARINTE II geht auch nicht!
         // VARINTE III -> geht:
          g.fillRect(posx,posy,70,60);
          posx=posx+i;
       }
     }
     public int getposx(){
        return posx;
     }
     public void dampfe(Graphics g){
          g.setColor(Color.white);
          pause();
          g.fillOval(posx+60,posy-60,20,20);

     }
    public boolean istLok_ausserhalb(){
       boolean ausserhalb;
       ausserhalb=false;
       if (posx>=300){
         ausserhalb=true;
       }
       return ausserhalb;
    }
      private void pause(){
      int millisec;
      millisec= (int) (Math.random()*100+50);
     try {
       Thread.sleep(millisec);
     } catch (InterruptedException e) {}
   }
  // Ende Methoden

 }

und hier dann mein Applet:

Code:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/**
  *
  * Beschreibung.
  *
  * @version 1.0 vom 14.02.2006
  * @author
  */

public class LokAppl extends Applet {
  // Anfang Variablen

  // Anfang Attribute
  private Panel cp = new Panel(null);
  private Button butLokerzeugen = new Button();
  private Button butFahren = new Button();
  private Button butClear = new Button();
  private Label labHinweis = new Label();
  
  Thread t1,t2;
  // Ende Attribute

  // Ende Variablen

  public void init() {

    cp.setBounds(0, 0, 300, 300);
    add(cp);
    cp.setBackground(Color.cyan);
    // Anfang Komponenten

    butLokerzeugen.setBounds(8, 8, 113, 33);
    butLokerzeugen.setLabel("Lokomotive erzeugen");
    cp.add(butLokerzeugen);
    butLokerzeugen.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        butLokerzeugenActionPerformed(evt);
      }
    });

    butFahren.setBounds(144, 8, 113, 33);
    butFahren.setLabel("Lokomotive fahren");
    cp.add(butFahren);
    butFahren.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        butFahrenActionPerformed(evt);
      }
    });

    butClear.setBounds(224, 240, 57, 25);
    butClear.setLabel("Clear");
    cp.add(butClear);
    butClear.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        butClearActionPerformed(evt);
      }
    });

    labHinweis.setBounds(0, 256, 208, 13);
    labHinweis.setText("");
    labHinweis.setFont(new Font("MS Sans Serif", Font.PLAIN, 13));
    cp.add(labHinweis);
    // Ende Komponenten

  }

  // Anfang Methoden
  // Anfang Ereignisprozeduren
  public void butLokerzeugenActionPerformed(ActionEvent evt) {

    labHinweis.setText("noch steht sie... ");
    Graphics g = cp.getGraphics();
    Lok myLok = new Lok(10,200,g,cp);

    myLok.malelok(g);
    myLok.dampfe(g);

  }
  public void butFahrenActionPerformed(ActionEvent evt) {
     Graphics g = cp.getGraphics();
     Lok myLok = new Lok(10,200,g,cp);
     Lok lok1 = new Lok(10,120,g,cp);

     t1= new Thread(myLok);
     t1.start();
     t2 = new Thread(lok1);
     t2.start();
     
     



  }
  public void butClearActionPerformed(ActionEvent evt) {
    cp.repaint();
    labHinweis.setText("");
  }
  // Ende Methoden
  // Ende Ereignisprozeduren

}
 
niemand ne Idee? hab heute nochmal alles mögliche versucht und bin leider nicht auf die richtige Lösung gekommen, dass es klappt.
 
Also ich würde zuerst mal auf Swing umstellen und die Lokomotiven per Timer bewegen, die Bewegung aber als Event in den EDT (Event-Dispatch-Thread) einspeißen.

Zeichenoperationen solltest du in der paint()- Methode (bzw. paintComponent() für Swing) durchführen, nicht in anderen Methoden. Auf gar keinen Fall solltest du von einem anderen Thread aus Zeichenoperationen durchführen!
Wenn du etwas Zeichnen willst, solltest du:
1. (am besten mit Timer oder in externem Thread): Alle nötigen Punkte/Werte berechnen
2. die Daten an dein Objekt übergeben (!! Threadsicherheit!!)
3. repaint() aufrufen
4. die paint() / paintComponent() - Methode soll deine Werte/Bilder/etc. darstellen
 
Hi
du erbst ja von Applet. Dieses Applet LokAppl hat eine paint metode, also ererbt...
Die Metode wird automatisch aufgerufen und malt das Applet weiß oder wie auch immer es aussieht(oder sie macht gar nichts).
Dann erzeugst du einen Zweiten Thread: Den Lok-Thread
Dieser Thread ruft repaint auf. Das sagt dem Appletthread, das er bei nächster gelegnheit paint von LokAppl aufrufen soll. Dann rufst du schnell deine Maloperationen auf, woraufhin diese auch ausgefügrt werden. Zu diesem Zeitpukt wird dann die paintmethode vom Appletthread aufgerufen.
und mach alles wieder Leer und du siehst garnichts.

Also entweder flackert es oder du siehst garnichts oder es wird ineinander gemalt aus.

genodeftest hat jedenfalls recht. Du musst die paintmethode vom Applet überschreiben.

Merken kannst du dir. Maloperationen NUR und wirklich nur innerhalb der Paintmethode aufrufen und nicht von sonstwo darauf rummalen durch speichern ges Graphicsobjekts. Das ist zwar möglich aber dazu muss man genau wissen, wie das malen vonstatten geht und das ist nicht so einfach.

Aber jetzt keine Panik, du musst die Lokklasse nicht komplet über den Haufen werfen. Du musst die malenfunktionen nur aus der paitfunktion des Applets aufrufen...

Ich hoffe das ich dir helfen konnte. Wenn nicht dann frag einfach nochmal spezifischer nach.

Ich würde unbedingt mal einen Blick hierauf werfen: http://mathsrv.ku-eichstaett.de/MGF/homes/grothmann/java/kurs/Applets.html

Das Beispiel habe ich auch von dort
Java:
public class HelloWorldApplet extends Applet
{   String s;
    public void init ()
    {   s=getParameter("Text");
        if (s==null) s="Hallo Welt!";
    }
    public void paint (Graphics g)
    {   g.drawString(s,50,50);
    }
}

Ach und JAVAcode immer so [JAVA ] [/ JAVA] einfassen
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück