Habe ich ein Synchronisationsproblem ?

Kanitrino

Bekanntes Mitglied
Hallo Wissende,

Ich habe ein Applet geschrieben. Es handelt sich um eine Animation, genauer gesagt, einen Zellulären Automaten.
Nun gibt es eine Klasse Rechner, die die neuen Bildpunkte berechnet, und eine Klasse Animation, die sie zeichnet.

Hier der relevante Teil der Klasse Animation

Java:
protected int anzBreite, anzHoehe, karo, breitePix, hoehePix, pix, rand=10;
	protected int[] pixels;
	protected MemoryImageSource source; 
	protected Image img;
	Color hintergrund;
	
	public Animation(int anzBreite, int anzHoehe, int karo, Color hintergrund)
	{
		this.anzBreite      = anzBreite;
		this.anzHoehe     = anzHoehe;
		this.karo 		= karo;
		this.hintergrund   = hintergrund;
		breitePix 		= anzBreite*karo;
		hoehePix		= anzHoehe*karo;
		pix			= breitePix*hoehePix;
		pixels			= new int[pix];
                source	        = new MemoryImageSource(breitePix, hoehePix, 
	    					pixels, 0, breitePix);
	  
	    source.setFullBufferUpdates(true);
	    source.setAnimated(true);
	    source.setFullBufferUpdates(true);
	    img	= createImage(source);
	    setBackground(hintergrund);
	    aktualisieren();
	}

         public void aktualisieren()
	 {
		 source.newPixels();
		 repaint();
	 }

	public void paint(Graphics g)
	{
		g.drawImage(img, rand, rand, this);
	}

	public void setPixels(int[] pixels)
	{
	    this.pixels = pixels;
	}
}

...und der Klasse Rechner
Java:
public class Rechner
....
       public void aktualisieren()
	{
		berechneBrett();
		brettInPixels();
		altern();
	}

       public void neuStart()
	{
		zufallsverteilung();
		brettInPixels();		
		altern();
	}

       private void brettInPixels()
	{
		int farbe;
		int[]pixels;
		pixels = animation.getPixels();
		
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
		{
			if(brettNeu[x][y]) farbe = blau;
			else		 	farbe = gelb;

			for(int a=0; a<karo; a++)
			for(int b=0; b<karo; b++)
				pixels[karo*x +a +(b+y*karo)*breitePix] = farbe;
		}	
		animation.setPixels(pixels);
	}

Nun gibt es noch ein Applet mit der run-Methode
Java:
public void run()
	{
		while(laeuft)
		{
			rechner.aktualisieren();
			animation.aktualisieren();
			verzoegerung(500);
		}
	}

und eine Gui, auf der man mit Hilfe eines Buttons das Bild neu initiieren kann
Java:
bStart = new JButton(start);
bStart.setBackground(gruen);
bStart.setSize(40, 60);
bStart.addActionListener
(new ActionListener()  // Start-Button
{	public void actionPerformed(ActionEvent e)
	{	
		if(rechner.getLaufen())
		{
			rechner.setLaufen(false);
			bStart.setBackground(gruen);
			bStart.setText(start);
			rechner.neuStart();
		}
				
		else 
		{
			rechner.setLaufen(true);
			bStart.setBackground(rot);
			bStart.setText(neu);	
		}
 }});
Die Berechnung des Bildes ist übrigens recht aufwändig. Es sind pro Zyklus immerhin ca. 100 000 Bildpunkte zu berechenem, was etwa 250 ms dauert.

Problem : Wenn ich die Animation laufen lasse und dann denn Button drücke, macht er entweder (a) was er soll, (b) nichts oder (c) er erzeugt ein Bild, das aus einer wilden Mischung zwischen dem neuen und dem alten besteht.

Ich vermute, dass die per Button ausgelöste Erzeugung des neuen Bildes rechner.neuStart(); in die laufende Berechnung des Bildes "hineinplatzt", anstatt abzuwarten, dass das aktualisieren() abgeschlossen ist.

Frage : Hat das was mit Synchronisation zu tun ?
Ich habe schon versucht, die Methoden mit "synchronized" zu markieren, das bringt aber nichts (außer dass wohl häufiger nichts erzeugt wird). In der Literatur finde ich den Begriff nur im Zusammenhang mit mehreren Threads - aber ich habe doch nur einen !

Was kann ich tun ?
 

Marco13

Top Contributor
Schwer zu sagen. Also, einfach zu sagen: Ja :) Aber woran genau es liegt... Wie genau es bei Applets ist, müßte ich erst nachsehen, aber i.a. gibt es zumindest gibt es 2 Threads, die sich in die Quere kommen können: Den "main" Thread, und den "Event Dispatch Thread" (letzterer verarbeitet Button Klicks und das Zeichnen).
Ein KSKB wäre wohl nicht schlecht.
 

Kanitrino

Bekanntes Mitglied
Aha, ein Action Event ist also auch ein Thread... Dann muss ich also doch die Kapitel mt den zwei Threads lesen.
Geht das dann mit wait() und notify() ?

Jetzt müsste mir noch jemand KSKB ins Neuhochdeutsche übersetzen - bei Gurgel finde ich da nur was über Kickboxen.
 

XHelp

Top Contributor
Du könntest auch über KSKB hier im Forum mit der Maus drüberfahren und dir die Erklärung "Kurzes Selbstständiges Kompilierbares Beispiel" durchlesen ;)
 

Marco13

Top Contributor
Ein ActionEvent ist kein Thread. Aber er wird von besagtem Event-Dispatch-Thread verarbeitet. Das ist der Thread, der sich bei Swing um alles kümmert, das mit der Oberfläche zu tun hat: Zeichnen, Events verarbeiten... (Jo, das war's eigentlich schon :oops: aber damit hat er auch schon genug zu tun ;) )
 

Kanitrino

Bekanntes Mitglied
Und wenn der Event-nicht-Thread warten soll, bis das normale Programm zu Ende aktualisiert hat ? Ist er dann als Thread zu behandeln ? Muss an ihm eine niedrige Priorität zuweisen ? Wait-en lassen, bis er notify-t wird ? Ein-locken ? Als Objekt synchronisieren (ist er denn eines) ? Die Methoden synchronisieren ? Irgendeine try-catch-Akrobatik vollführen ?

Also nochmal im Klartext : Was muss ich tun, um eine durch ein Action-Event ausgelöste Methode so lange warten zu lassen bis sie dran ist ?
 

Murray

Top Contributor
Was muss ich tun, um eine durch ein Action-Event ausgelöste Methode so lange warten zu lassen bis sie dran ist ?
Was bedeutet denn "dran sein"? Normalerweise würde man sich doch wünschen, dass Events möglichst schnell verarbeitet werden und nicht auf irgendwelche Signale warten müssen.
Du musst Dir darüber im Klaren sein, dass die Action-Events in einem eigenen Thread ausgeführt werden, über den Du wenig Kontrolle hast. Das kann dann zum Problem werden, wenn es auch noch andere Threads (z.B. den Main-Thread) gibt, die Resourcen nutzen, die ebenfalls von den Action-Events verwendet werden.
Aus dem von Dir geposteten Code wird mir allerdings noch nicht klar, wo diese Konflikte bestehen.
 

Kanitrino

Bekanntes Mitglied
Was bedeutet denn "dran sein"? ...
Aus dem von Dir geposteten Code wird mir allerdings noch nicht klar, wo diese Konflikte bestehen.
Ich vermute, das Problem ist dies : Zum Ausrechnen der neuen Pixels (und deren Übergabe ans Image, das dann gezeichnet wird) wird eine lange Zeit benötigt - 250 ms. Wenn in dieser Zeit der Neustart-Button betätigt wird, wird ein ganz anders Bild (nämlich das Start-Bild) erzeugt und soll ebenfalls gezeichnet werden.
Diese beiden Aktivitäten kommen sich also in die Quere und es wird ein Bild erzeugt, das eine wilde Mischung aus beiden darstellt. Die Lösung wäre dann : immer hübsch eines nach dem anderen.

Aber wie sage ich "ihm" das auf Javaianisch ?
 

JanHH

Top Contributor
In einer graphischen Anwendung (also, Programm mit graphischer Benutzeroberfläche) sollte es gar keine main-Funktion geben, die irgendwas tut, ausser die Anwendung zusammenzubauen und das Hauptfenster anzuzeigen. Die run-Methode des applets dürfte ja das Pendat zur main-Funktion sein.

Programme mit graphischer Benutzeroberfläche funktionieren anders: Sie verharren quasi in einem passiven Wartezustand, bzw. in besagtem Event-Dispatch-Thread, und reagieren ereignisgesteuert. Wenn da nun ständig "von selber" etwas vor sich hin animiert werden soll, dann gibts da in der Tat ein Synchronisationsproblem. Aber das bei einer Swing-Oberfläche hinzukriegen ist nicht allzu schwierig. Wird sicherlich an einigen Stellen in der Literatur gut erklärt ;-).
 

Marco13

Top Contributor
Das Stichwort, das hier am schnellsten und einfachsten helfen würde (bzw. schon geholfen hätte) wurde schon genannt: KSKB. Wenn man dein Programm einfach rauskopieren, compilieren und starten könnte, würde man erstens das Problem deutlicher sehen als "da wird was gezeichnet, was ich nicht will", und zweitens (wichtig) würde man erkennen, wer wann welche Methode von wo aus aufruft.

Bis dahin nur ein Tipp: Du darst das Ausrechnen nicht in der run-Methode des Applets machen, sondern NUR in irgendwelchen Listener-Methoden, z.B. in der ActionPerformed von irgendeinem Button. Dann blockiert zwar das GUI solange er rechnet, und das ist eigentlich schei*, aber deinen Ausführungen nach ja genau das, was du willst.

Um noch genauer zu werden:
Diese beiden Aktivitäten kommen sich also in die Quere

Das ist das allgemeine, omnipräsente Problem, das mit dem Event-Dispatch-Thread gelöst werden soll. Nochmal: Wenn man eine Swing-Anwendung hat, läuft da dieser Event-Dispatch-Thread. Der kümmert sich um das Zeichnen, und um die Verarbeitung von Events (z.B. von Button-Klicks). Und es gibt die Regel, die frei übersetzt lautet:
Alles, was irgendwie den Zustand der Swing-Oberfläche verändert, oder vom Zustand der Swing-Oberfläche abhängt, muss vom Event-Dispatch-Thread gemacht werden!
Genaueres dazu auf Threads and Swing

Das Ziel, das man mit dieser Regel erreichen will, ist genau das, was DU erreichen willst: Wenn nur EIN Thread die Veränderungen macht, passiert automatisch "immer hübsch eines nach dem anderen".
 

Kanitrino

Bekanntes Mitglied
Also, jetzt ist es mir klar : Ich muss mich mit dem Thema "EventQueue" auseinandersetzen. Das war das Stichwort, das ich gebraucht habe.

Vielen Dank für Deine Hilfe !

Gottfried Benn hat gesagt.:
Woher, wohin -, nicht Nacht, nicht Morgen,
kein Evoë, kein Requiem,
du möchtest dir ein Stichwort borgen -,
allein bei wem?
 

Marco13

Top Contributor
Noch ein Hinweis dazu: Wenn man in "irgendeinem" Thread ist, kann man mit
Code:
SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        machWas();
    }
});
bewirken, dass "machWas()" auf dem Event Dispatch Thread ausgeführt wird.
 

Kanitrino

Bekanntes Mitglied
Wenn man dein Programm einfach rauskopieren, compilieren und starten könnte, würde man erstens das Problem deutlicher sehen als "da wird was gezeichnet, was ich nicht will", und zweitens (wichtig) würde man erkennen, wer wann welche Methode von wo aus aufruft.
Okay, dann schreibe ich im Folgenden das komplette Programm rein (alle Klassen hinereinander) :

Java:
import java.awt.BorderLayout;
import javax.swing.JApplet;
import javax.swing.JPanel;

public class AppletDiffusion extends JApplet implements Runnable 
{
	private static final long serialVersionUID = 1L;
	Thread running;
	protected boolean laeuft= false;
	protected static int msec;
	
	public void init(){}
	public void run(){}
	
	protected void setzeLayout(Animation animation, JPanel gui)
	{
		this.setLayout(new BorderLayout());
		this.add("East", gui);
		this.add("Center", animation);
	}
	
	public void setLaufen(boolean laeuft)
	{
		this.laeuft = laeuft;
		start();
	}
	
	public boolean getLaufen()
	{
		return laeuft;
	}
	
	public void start()
	{	if (running == null);
		{	running = new Thread(this);
			running.start();
	}	}
	
	public void stop()
	{	running = null;
	}
	
	public void verzoegerung()
	{	try {Thread.sleep (msec);}
		catch(Exception e){}
	}
}

//**********************************

import java.awt.BorderLayout;
import java.awt.Color;

public class MusterSimulation extends AppletDiffusion
{
	private static final long serialVersionUID = 1L;
	private int karo 		= 1;
	private int anzBreite 	= 300/karo;
	private int anzHoehe 	= 300/karo;
	Animation animation;
	MusterRechner rechner;
	MusterGui gui;
	Color hintergrund = new Color(120, 250, 210);

	public void init()
	{
		msec 	  = 500;
		animation = new Animation(anzBreite, anzHoehe, karo, hintergrund);
		rechner	  = new MusterRechner(animation, this);
		gui		  = new MusterGui(rechner, hintergrund);
		this.setLayout(new BorderLayout());
		setzeLayout(animation, gui);
	}
	
	public void run()
	{
		while(laeuft)
		{
			rechner.aktualisieren();
			animation.aktualisieren();
			verzoegerung();
		}
	}
}

//**********************************

package de.kanitrino.diffusion;
import de.kanitrino.wolfram.Animation;

public class MusterRechner 
{
	Animation animation;
	AppletDiffusion applet;
	protected int anzBreite, anzHoehe, breitePix, hoehePix, karo, pix;
	protected double faktor;
	boolean[][]brettAlt, brettNeu;
	private final int blau = 255 | 255 << 24;
	private final int gelb = 255 << 8 | 255 << 16 | 255 << 24;
	
	public MusterRechner(Animation animation, AppletDiffusion applet)
	{
		this.animation 	= animation;
		this.applet 	= applet;
		anzBreite		= animation.getAnzBreite();
		anzHoehe 		= animation.getAnzHoehe();
		karo 			= animation.getKaro();
		breitePix		= anzBreite*karo;
		hoehePix		= anzHoehe*karo;
		pix				= breitePix*hoehePix;
		brettAlt		= new boolean[anzBreite][anzHoehe];
		brettNeu		= new boolean[anzBreite][anzHoehe];
		brettLeeren();
		neuStart();
	}
	
	public void neuStart()
	{
		zufallsverteilung();
		brettInPixels();		
		altern();
	}

	public void aktualisieren()
	{
		berechneBrett();
		brettInPixels();
		altern();
	}
	
	public void brettLeeren()
	{
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
			brettNeu[x][y]=false;
	}
	
	public void zufallsverteilung()
	{	
		double saat = Math.random()/2.;
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
			if((x-anzBreite/2)*(x-anzBreite/2)
			  +(y-anzHoehe/2)*(y-anzHoehe/2) 
			  < (anzBreite*anzBreite/6)) 
					brettNeu[x][y] = Math.random()<saat;
			else 	brettNeu[x][y] = false;
	}
	
	private void altern()
	{
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
			brettAlt[x][y]	= brettNeu[x][y];
	}
	
	private void berechneBrett()
	{
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
		{
			double wert1 =0;			
			wert1 += (double)(zaehle(x, y, 0))*4;
			wert1 += (double) zaehle(x, y, 1);
			wert1 += (double)(zaehle(x, y, 2))/Math.sqrt(2.);		
			wert1 += (double)(zaehle(x, y, 3))/2.;		
			wert1 += (double)(zaehle(x, y, 4))/Math.sqrt(5.);	
			
			double wert2 =0;
						
//			wert2 += (double)(zaehle(x, y, 5))/Math.sqrt(8.);		
//			wert2 += (double)(zaehle(x, y, 6))/3.;
//			wert2 += (double)(zaehle(x, y, 7))/Math.sqrt(10.);
			wert2 += (double)(zaehle(x, y, 8))/Math.sqrt(13.);
			wert2 += (double)(zaehle(x, y, 9))/4.;
			wert2 += (double)(zaehle(x, y, 10))/Math.sqrt(17.);			
			wert2 += (double)(zaehle(x, y, 11))/Math.sqrt(18.);
			wert2 += (double)(zaehle(x, y, 12))/Math.sqrt(20.);
			wert2 += (double)(zaehle(x, y, 13))/5.;
			wert2 += (double)(zaehle(x, y, 14))/Math.sqrt(26.);
			
			wert2 *= faktor;
			
			if(wert1 > wert2) brettNeu[x][y] = true;
			else 			  brettNeu[x][y] = false;
		}
	}
	
	private void brettInPixels()
	{
		int farbe;
		int[]pixels;
		pixels = animation.getPixels();
		
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
		{
			if(brettNeu[x][y]) farbe = blau;
			else		 	   farbe = gelb;

			for(int a=0; a<karo; a++)
			for(int b=0; b<karo; b++)
				pixels[karo*x +a +(b+y*karo)*breitePix] = farbe;
		}	
		animation.setPixels(pixels);
	}	
	
	private int zaehle(int x, int y, int nah)
	{
		int anz = 0;
		int x01, x02, x03, x04, x05, xx1, xx2, xx3, xx4, xx5, 
			y01, y02, y03, y04, y05, yy1, yy2, yy3, yy4, yy5;
		
		x01 = (x-1+anzBreite)%anzBreite;
		xx1 = (x+1)%anzBreite;
		y01 = (y-1+anzHoehe)%anzHoehe;
		yy1 = (y+1)%anzHoehe;
		
		x02 = (x-2+anzBreite)%anzBreite;
		xx2 = (x+2)%anzBreite;
		y02 = (y-2+anzHoehe)%anzHoehe;
		yy2 = (y+2)%anzHoehe;
		
		x03 = (x-3+anzBreite)%anzBreite;
		xx3 = (x+3)%anzBreite;
		y03 = (y-3+anzHoehe)%anzHoehe;
		yy3 = (y+3)%anzHoehe;
		
		x04 = (x-4+anzBreite)%anzBreite;
		xx4 = (x+4)%anzBreite;
		y04 = (y-4+anzHoehe)%anzHoehe;
		yy4 = (y+4)%anzHoehe;
		
		x05 = (x-5+anzBreite)%anzBreite;
		xx5 = (x+5)%anzBreite;
		y05 = (y-5+anzHoehe)%anzHoehe;
		yy5 = (y+5)%anzHoehe;
		
		if(nah==0)
		{
			if(brettAlt[x][y]) anz++;
		}
		
		else if(nah==1)
		{
			if(brettAlt[x01][y]) anz++;
			if(brettAlt[xx1][y]) anz++;
			if(brettAlt[x][y01]) anz++;
			if(brettAlt[x][yy1]) anz++;
		}
		else if(nah==2)
		{
			if(brettAlt[x01][y01]) anz++;
			if(brettAlt[xx1][y01]) anz++;
			if(brettAlt[x01][yy1]) anz++;
			if(brettAlt[xx1][yy1]) anz++;
		}
		
		else if(nah==3)
		{
			if(brettAlt[x02][y]) anz++;
			if(brettAlt[xx2][y]) anz++;
			if(brettAlt[x][y02]) anz++;
			if(brettAlt[x][yy2]) anz++;
		}
		
		else if(nah==4)
		{
			if(brettAlt[x02][y01]) anz++;
			if(brettAlt[x02][yy1]) anz++;
			if(brettAlt[x01][y02]) anz++;
			if(brettAlt[x01][yy2]) anz++;
			
			if(brettAlt[xx1][y02]) anz++;
			if(brettAlt[xx1][yy2]) anz++;
			if(brettAlt[xx2][y01]) anz++;
			if(brettAlt[xx2][yy1]) anz++;			
		}
		
		else if(nah==5)
		{
			if(brettAlt[x02][y02]) anz++;
			if(brettAlt[xx2][y02]) anz++;
			if(brettAlt[x02][yy2]) anz++;
			if(brettAlt[xx2][yy2]) anz++;
		}
		
		else if (nah==6)
		{
			if(brettAlt[x][y03]) anz++;
			if(brettAlt[x][yy3]) anz++;
			if(brettAlt[x03][y]) anz++;
			if(brettAlt[x03][y]) anz++;
		}
		
		else if(nah==7)
		{
			if(brettAlt[x03][y01]) anz++;
			if(brettAlt[x03][yy1]) anz++;
			if(brettAlt[x01][y03]) anz++;
			if(brettAlt[x01][yy3]) anz++;
			
			if(brettAlt[xx1][y03]) anz++;
			if(brettAlt[xx1][yy3]) anz++;
			if(brettAlt[xx3][y01]) anz++;
			if(brettAlt[xx3][yy1]) anz++;			
		}
		
		else if(nah==8)
		{
			if(brettAlt[x03][y02]) anz++;
			if(brettAlt[x03][yy2]) anz++;
			if(brettAlt[x02][y03]) anz++;
			if(brettAlt[x02][yy3]) anz++;
			
			if(brettAlt[xx2][y03]) anz++;
			if(brettAlt[xx2][yy3]) anz++;
			if(brettAlt[xx3][y02]) anz++;
			if(brettAlt[xx3][yy2]) anz++;			
		}
		
		else if(nah==9)
		{
			if(brettAlt[x][y04]) anz++;
			if(brettAlt[x][yy4]) anz++;
			if(brettAlt[x04][y]) anz++;
			if(brettAlt[xx4][y]) anz++;
		}
		
		else if(nah==10)
		{
			if(brettAlt[x01][y04]) anz++;
			if(brettAlt[x01][yy4]) anz++;
			if(brettAlt[x04][y01]) anz++;
			if(brettAlt[x04][yy1]) anz++;
			
			if(brettAlt[xx1][y04]) anz++;
			if(brettAlt[xx1][yy4]) anz++;	
			if(brettAlt[xx4][y01]) anz++;
			if(brettAlt[xx4][yy1]) anz++;		
		}
			
		else if(nah==11)
		{
			if(brettAlt[x03][y03]) anz++;
			if(brettAlt[x03][yy3]) anz++;
			if(brettAlt[xx3][y03]) anz++;
			if(brettAlt[xx3][yy3]) anz++;
		}
		
		else if(nah==12)
		{
			if(brettAlt[x02][y04]) anz++;
			if(brettAlt[x02][yy4]) anz++;
			if(brettAlt[x04][y02]) anz++;
			if(brettAlt[x04][yy2]) anz++;
			
			if(brettAlt[xx2][y04]) anz++;
			if(brettAlt[xx2][yy4]) anz++;	
			if(brettAlt[xx4][y02]) anz++;
			if(brettAlt[xx4][yy2]) anz++;		
		}
		
		else if(nah==13)
		{
			if(brettAlt[x03][y04]) anz++;
			if(brettAlt[x03][yy4]) anz++;
			if(brettAlt[x04][y03]) anz++;
			if(brettAlt[x04][yy3]) anz++;
			
			if(brettAlt[xx3][y04]) anz++;
			if(brettAlt[xx3][yy4]) anz++;	
			if(brettAlt[xx4][y03]) anz++;
			if(brettAlt[xx4][yy3]) anz++;
			
			if(brettAlt[x][y05]) anz++;
			if(brettAlt[x][yy5]) anz++;
			if(brettAlt[x05][y]) anz++;
			if(brettAlt[xx5][y]) anz++;
		}
		
		else if(nah==14)
		{
			if(brettAlt[x01][y05]) anz++;
			if(brettAlt[x01][yy5]) anz++;
			if(brettAlt[x05][y01]) anz++;
			if(brettAlt[x05][yy1]) anz++;
			
			if(brettAlt[xx1][y05]) anz++;
			if(brettAlt[xx1][yy5]) anz++;	
			if(brettAlt[xx5][y01]) anz++;
			if(brettAlt[xx5][yy1]) anz++;		
		}
		else anz= -1;
		return anz;
	}
	
	public void setFaktor(double faktor)
	{
		this.faktor = faktor;
	}
	
	public void setLaufen(boolean laeuft)
	{
		applet.setLaufen(laeuft);
	}
	
	public boolean getLaufen()
	{
		return applet.getLaufen();
	}
}

//************************************

package de.kanitrino.wolfram;

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Image;
import java.awt.image.MemoryImageSource;

public class Animation extends Canvas
{
	private static final long serialVersionUID = 1L;
	protected int anzBreite, anzHoehe, karo, breitePix, hoehePix, pix,
		rand=10;
	protected int[] pixels;
	protected MemoryImageSource source; 
	protected Image img;
	Color hintergrund;
	
	public Animation(int anzBreite, int anzHoehe, int karo, Color hintergrund)
	{
		this.anzBreite = anzBreite;
		this.anzHoehe   = anzHoehe;
		this.karo 		= karo;
		this.hintergrund= hintergrund;
		breitePix 		= anzBreite*karo;
		hoehePix		= anzHoehe*karo;
		pix			= breitePix*hoehePix;
		pixels			= new int[pix];
	    source			= new MemoryImageSource(breitePix, hoehePix, 
	    					pixels, 0, breitePix);
	  
	    source.setFullBufferUpdates(true);
	    source.setAnimated(true);
	    source.setFullBufferUpdates(true);
	    img	= createImage(source);
	    setBackground(hintergrund);
	    aktualisieren();
	}
	
	 public void aktualisieren()
	 {
		 source.newPixels();
		 repaint();
	 }

	public void paint(Graphics g)
	{
		g.drawImage(img, rand, rand, this);
	}

	public int[] getPixels()
	{
		return pixels;
	}
	
	public void setPixels(int[] pixels)
	{
	    this.pixels = pixels;
	}
	
	public void faerbeImage(int farbe)
	{
		for(int i=0; i<pix; i++)
			pixels[i] = farbe;
	}
	
	public void faerbeImage(int farbe1, int farbe2)
	{
		for(int i=0; i<pix; i++)
			if(Math.random()<0.5) pixels[i] = farbe1;
			else				  pixels[i] = farbe2;
	}
	
	public int getAnzBreite()
	{
		return anzBreite;
	}
	
	public int getAnzHoehe()
	{
		return anzHoehe;
	}
	
	public int getKaro()
	{
		return karo;
	}
	
	public Dimension getPreferredSize() 
	{	return new Dimension(breitePix+2*rand, hoehePix+2*rand);}
	
	
	public void update (Graphics screen)
	{paint (screen);}
}
 

Kanitrino

Bekanntes Mitglied
Wenn man dein Programm einfach rauskopieren, compilieren und starten könnte, würde man erstens das Problem deutlicher sehen als "da wird was gezeichnet, was ich nicht will", und zweitens (wichtig) würde man erkennen, wer wann welche Methode von wo aus aufruft.
Ich habe jetzt verschiedene Sachen versucht und es klappt immer noch nicht.
(Problem : Beim Drücken des Random-Buttons soll das Bild wieder "Schneegestöber" sein)

Okay, dann schreibe ich im Folgenden das komplette Programm rein (alle Klassen hintereinander) :

Java:
import java.awt.BorderLayout;
import javax.swing.JApplet;
import javax.swing.JPanel;

public class AppletDiffusion extends JApplet implements Runnable 
{
	private static final long serialVersionUID = 1L;
	Thread running;
	protected boolean laeuft= false;
	protected static int msec;
	
	public void init(){}
	public void run(){}
	
	protected void setzeLayout(Animation animation, JPanel gui)
	{
		this.setLayout(new BorderLayout());
		this.add("East", gui);
		this.add("Center", animation);
	}
	
	public void setLaufen(boolean laeuft)
	{
		this.laeuft = laeuft;
		start();
	}
	
	public boolean getLaufen()
	{
		return laeuft;
	}
	
	public void start()
	{	if (running == null);
		{	running = new Thread(this);
			running.start();
	}	}
	
	public void stop()
	{	running = null;
	}
	
	public void verzoegerung()
	{	try {Thread.sleep (msec);}
		catch(Exception e){}
	}
}

//**********************************

import java.awt.BorderLayout;
import java.awt.Color;

public class MusterSimulation extends AppletDiffusion
{
	private static final long serialVersionUID = 1L;
	private int karo 		= 1;
	private int anzBreite 	= 300/karo;
	private int anzHoehe 	= 300/karo;
	Animation animation;
	MusterRechner rechner;
	MusterGui gui;
	Color hintergrund = new Color(120, 250, 210);

	public void init()
	{
		msec 	  = 500;
		animation = new Animation(anzBreite, anzHoehe, karo, hintergrund);
		rechner	  = new MusterRechner(animation, this);
		gui		  = new MusterGui(rechner, hintergrund);
		this.setLayout(new BorderLayout());
		setzeLayout(animation, gui);
	}
	
	public void run()
	{
		while(laeuft)
		{
			rechner.aktualisieren();
			animation.aktualisieren();
			verzoegerung();
		}
	}
}

//**********************************

public class MusterRechner 
{
	Animation animation;
	AppletDiffusion applet;
	protected int anzBreite, anzHoehe, breitePix, hoehePix, karo, pix;
	protected double faktor;
	boolean[][]brettAlt, brettNeu;
	private final int blau = 255 | 255 << 24;
	private final int gelb = 255 << 8 | 255 << 16 | 255 << 24;
	
	public MusterRechner(Animation animation, AppletDiffusion applet)
	{
		this.animation 	= animation;
		this.applet 	= applet;
		anzBreite		= animation.getAnzBreite();
		anzHoehe 		= animation.getAnzHoehe();
		karo 			= animation.getKaro();
		breitePix		= anzBreite*karo;
		hoehePix		= anzHoehe*karo;
		pix				= breitePix*hoehePix;
		brettAlt		= new boolean[anzBreite][anzHoehe];
		brettNeu		= new boolean[anzBreite][anzHoehe];
		brettLeeren();
		neuStart();
	}
	
	public void neuStart()
	{
		zufallsverteilung();
		brettInPixels();		
		altern();
	}

	public void aktualisieren()
	{
		berechneBrett();
		brettInPixels();
		altern();
	}
	
	public void brettLeeren()
	{
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
			brettNeu[x][y]=false;
	}
	
	public void zufallsverteilung()
	{	
		double saat = Math.random()/2.;
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
			if((x-anzBreite/2)*(x-anzBreite/2)
			  +(y-anzHoehe/2)*(y-anzHoehe/2) 
			  < (anzBreite*anzBreite/6)) 
					brettNeu[x][y] = Math.random()<saat;
			else 	brettNeu[x][y] = false;
	}
	
	private void altern()
	{
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
			brettAlt[x][y]	= brettNeu[x][y];
	}
	
	private void berechneBrett()
	{
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
		{
			double wert1 =0;			
			wert1 += (double)(zaehle(x, y, 0))*4;
			wert1 += (double) zaehle(x, y, 1);
			wert1 += (double)(zaehle(x, y, 2))/Math.sqrt(2.);		
			wert1 += (double)(zaehle(x, y, 3))/2.;		
			wert1 += (double)(zaehle(x, y, 4))/Math.sqrt(5.);	
			
			double wert2 =0;
						
//			wert2 += (double)(zaehle(x, y, 5))/Math.sqrt(8.);		
//			wert2 += (double)(zaehle(x, y, 6))/3.;
//			wert2 += (double)(zaehle(x, y, 7))/Math.sqrt(10.);
			wert2 += (double)(zaehle(x, y, 8))/Math.sqrt(13.);
			wert2 += (double)(zaehle(x, y, 9))/4.;
			wert2 += (double)(zaehle(x, y, 10))/Math.sqrt(17.);			
			wert2 += (double)(zaehle(x, y, 11))/Math.sqrt(18.);
			wert2 += (double)(zaehle(x, y, 12))/Math.sqrt(20.);
			wert2 += (double)(zaehle(x, y, 13))/5.;
			wert2 += (double)(zaehle(x, y, 14))/Math.sqrt(26.);
			
			wert2 *= faktor;
			
			if(wert1 > wert2) brettNeu[x][y] = true;
			else 			  brettNeu[x][y] = false;
		}
	}
	
	private void brettInPixels()
	{
		int farbe;
		int[]pixels;
		pixels = animation.getPixels();
		
		for(int y=0; y<anzHoehe; y++)
		for(int x=0; x<anzBreite; x++)
		{
			if(brettNeu[x][y]) farbe = blau;
			else		 	   farbe = gelb;

			for(int a=0; a<karo; a++)
			for(int b=0; b<karo; b++)
				pixels[karo*x +a +(b+y*karo)*breitePix] = farbe;
		}	
		animation.setPixels(pixels);
	}	
	
	private int zaehle(int x, int y, int nah)
	{
		int anz = 0;
		int x01, x02, x03, x04, x05, xx1, xx2, xx3, xx4, xx5, 
			y01, y02, y03, y04, y05, yy1, yy2, yy3, yy4, yy5;
		
		x01 = (x-1+anzBreite)%anzBreite;
		xx1 = (x+1)%anzBreite;
		y01 = (y-1+anzHoehe)%anzHoehe;
		yy1 = (y+1)%anzHoehe;
		
		x02 = (x-2+anzBreite)%anzBreite;
		xx2 = (x+2)%anzBreite;
		y02 = (y-2+anzHoehe)%anzHoehe;
		yy2 = (y+2)%anzHoehe;
		
		x03 = (x-3+anzBreite)%anzBreite;
		xx3 = (x+3)%anzBreite;
		y03 = (y-3+anzHoehe)%anzHoehe;
		yy3 = (y+3)%anzHoehe;
		
		x04 = (x-4+anzBreite)%anzBreite;
		xx4 = (x+4)%anzBreite;
		y04 = (y-4+anzHoehe)%anzHoehe;
		yy4 = (y+4)%anzHoehe;
		
		x05 = (x-5+anzBreite)%anzBreite;
		xx5 = (x+5)%anzBreite;
		y05 = (y-5+anzHoehe)%anzHoehe;
		yy5 = (y+5)%anzHoehe;
		
		if(nah==0)
		{
			if(brettAlt[x][y]) anz++;
		}
		
		else if(nah==1)
		{
			if(brettAlt[x01][y]) anz++;
			if(brettAlt[xx1][y]) anz++;
			if(brettAlt[x][y01]) anz++;
			if(brettAlt[x][yy1]) anz++;
		}
		else if(nah==2)
		{
			if(brettAlt[x01][y01]) anz++;
			if(brettAlt[xx1][y01]) anz++;
			if(brettAlt[x01][yy1]) anz++;
			if(brettAlt[xx1][yy1]) anz++;
		}
		
		else if(nah==3)
		{
			if(brettAlt[x02][y]) anz++;
			if(brettAlt[xx2][y]) anz++;
			if(brettAlt[x][y02]) anz++;
			if(brettAlt[x][yy2]) anz++;
		}
		
		else if(nah==4)
		{
			if(brettAlt[x02][y01]) anz++;
			if(brettAlt[x02][yy1]) anz++;
			if(brettAlt[x01][y02]) anz++;
			if(brettAlt[x01][yy2]) anz++;
			
			if(brettAlt[xx1][y02]) anz++;
			if(brettAlt[xx1][yy2]) anz++;
			if(brettAlt[xx2][y01]) anz++;
			if(brettAlt[xx2][yy1]) anz++;			
		}
		
		else if(nah==5)
		{
			if(brettAlt[x02][y02]) anz++;
			if(brettAlt[xx2][y02]) anz++;
			if(brettAlt[x02][yy2]) anz++;
			if(brettAlt[xx2][yy2]) anz++;
		}
		
		else if (nah==6)
		{
			if(brettAlt[x][y03]) anz++;
			if(brettAlt[x][yy3]) anz++;
			if(brettAlt[x03][y]) anz++;
			if(brettAlt[x03][y]) anz++;
		}
		
		else if(nah==7)
		{
			if(brettAlt[x03][y01]) anz++;
			if(brettAlt[x03][yy1]) anz++;
			if(brettAlt[x01][y03]) anz++;
			if(brettAlt[x01][yy3]) anz++;
			
			if(brettAlt[xx1][y03]) anz++;
			if(brettAlt[xx1][yy3]) anz++;
			if(brettAlt[xx3][y01]) anz++;
			if(brettAlt[xx3][yy1]) anz++;			
		}
		
		else if(nah==8)
		{
			if(brettAlt[x03][y02]) anz++;
			if(brettAlt[x03][yy2]) anz++;
			if(brettAlt[x02][y03]) anz++;
			if(brettAlt[x02][yy3]) anz++;
			
			if(brettAlt[xx2][y03]) anz++;
			if(brettAlt[xx2][yy3]) anz++;
			if(brettAlt[xx3][y02]) anz++;
			if(brettAlt[xx3][yy2]) anz++;			
		}
		
		else if(nah==9)
		{
			if(brettAlt[x][y04]) anz++;
			if(brettAlt[x][yy4]) anz++;
			if(brettAlt[x04][y]) anz++;
			if(brettAlt[xx4][y]) anz++;
		}
		
		else if(nah==10)
		{
			if(brettAlt[x01][y04]) anz++;
			if(brettAlt[x01][yy4]) anz++;
			if(brettAlt[x04][y01]) anz++;
			if(brettAlt[x04][yy1]) anz++;
			
			if(brettAlt[xx1][y04]) anz++;
			if(brettAlt[xx1][yy4]) anz++;	
			if(brettAlt[xx4][y01]) anz++;
			if(brettAlt[xx4][yy1]) anz++;		
		}
			
		else if(nah==11)
		{
			if(brettAlt[x03][y03]) anz++;
			if(brettAlt[x03][yy3]) anz++;
			if(brettAlt[xx3][y03]) anz++;
			if(brettAlt[xx3][yy3]) anz++;
		}
		
		else if(nah==12)
		{
			if(brettAlt[x02][y04]) anz++;
			if(brettAlt[x02][yy4]) anz++;
			if(brettAlt[x04][y02]) anz++;
			if(brettAlt[x04][yy2]) anz++;
			
			if(brettAlt[xx2][y04]) anz++;
			if(brettAlt[xx2][yy4]) anz++;	
			if(brettAlt[xx4][y02]) anz++;
			if(brettAlt[xx4][yy2]) anz++;		
		}
		
		else if(nah==13)
		{
			if(brettAlt[x03][y04]) anz++;
			if(brettAlt[x03][yy4]) anz++;
			if(brettAlt[x04][y03]) anz++;
			if(brettAlt[x04][yy3]) anz++;
			
			if(brettAlt[xx3][y04]) anz++;
			if(brettAlt[xx3][yy4]) anz++;	
			if(brettAlt[xx4][y03]) anz++;
			if(brettAlt[xx4][yy3]) anz++;
			
			if(brettAlt[x][y05]) anz++;
			if(brettAlt[x][yy5]) anz++;
			if(brettAlt[x05][y]) anz++;
			if(brettAlt[xx5][y]) anz++;
		}
		
		else if(nah==14)
		{
			if(brettAlt[x01][y05]) anz++;
			if(brettAlt[x01][yy5]) anz++;
			if(brettAlt[x05][y01]) anz++;
			if(brettAlt[x05][yy1]) anz++;
			
			if(brettAlt[xx1][y05]) anz++;
			if(brettAlt[xx1][yy5]) anz++;	
			if(brettAlt[xx5][y01]) anz++;
			if(brettAlt[xx5][yy1]) anz++;		
		}
		else anz= -1;
		return anz;
	}
	
	public void setFaktor(double faktor)
	{
		this.faktor = faktor;
	}
	
	public void setLaufen(boolean laeuft)
	{
		applet.setLaufen(laeuft);
	}
	
	public boolean getLaufen()
	{
		return applet.getLaufen();
	}
}

//************************************

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Image;
import java.awt.image.MemoryImageSource;

public class Animation extends Canvas
{
	private static final long serialVersionUID = 1L;
	protected int anzBreite, anzHoehe, karo, breitePix, hoehePix, pix,
		rand=10;
	protected int[] pixels;
	protected MemoryImageSource source; 
	protected Image img;
	Color hintergrund;
	
	public Animation(int anzBreite, int anzHoehe, int karo, Color hintergrund)
	{
		this.anzBreite = anzBreite;
		this.anzHoehe   = anzHoehe;
		this.karo 		= karo;
		this.hintergrund= hintergrund;
		breitePix 		= anzBreite*karo;
		hoehePix		= anzHoehe*karo;
		pix			= breitePix*hoehePix;
		pixels			= new int[pix];
	        source			= new MemoryImageSource(breitePix, hoehePix, 
	    					pixels, 0, breitePix);
	  
	    source.setFullBufferUpdates(true);
	    source.setAnimated(true);
	    source.setFullBufferUpdates(true);
	    img	= createImage(source);
	    setBackground(hintergrund);
	    aktualisieren();
	}
	
	 public void aktualisieren()
	 {
		 source.newPixels();
		 repaint();
	 }

	public void paint(Graphics g)
	{
		g.drawImage(img, rand, rand, this);
	}

	public int[] getPixels()
	{
		return pixels;
	}
	
	public void setPixels(int[] pixels)
	{
	    this.pixels = pixels;
	}
	
	public void faerbeImage(int farbe)
	{
		for(int i=0; i<pix; i++)
			pixels[i] = farbe;
	}
	
	public void faerbeImage(int farbe1, int farbe2)
	{
		for(int i=0; i<pix; i++)
			if(Math.random()<0.5) pixels[i] = farbe1;
			else				  pixels[i] = farbe2;
	}
	
	public int getAnzBreite()
	{
		return anzBreite;
	}
	
	public int getAnzHoehe()
	{
		return anzHoehe;
	}
	
	public int getKaro()
	{
		return karo;
	}
	
	public Dimension getPreferredSize() 
	{	return new Dimension(breitePix+2*rand, hoehePix+2*rand);}
	
	
	public void update (Graphics screen)
	{paint (screen);}
}

//************************************

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class MusterGui extends JPanel 
{
	private static final long serialVersionUID = 1L;
	MusterRechner rechner;
	JButton bStart;
	JSlider slider;
   	Label label1, label2, label3;
   	String start, neu;
	Font font1, font2, font3;
	Panel panel1, panel2, panel3, panel4;
	Color rot, gruen;
	
	public MusterGui(MusterRechner rechner, Color hintergrund)
	{
		this.rechner = rechner;
		start = "   S T A R T    ";
		neu   = "  R A N D O M  ";
		gruen = new Color(120, 250, 110);
		rot = new Color(250, 120, 75);
		setKomponenten();
		setLabel();
		rechner.setFaktor((double)(slider.getValue())/10.);
		setBackground(hintergrund);
	}
	
	public void setKomponenten()
	{
		font1	= new Font("VERDANA",Font.BOLD,26);
		font2	= new Font("VERDANA",Font.PLAIN,12);
		font3	= new Font("VERDANA",Font.PLAIN,10);
			
		slider = new JSlider(JSlider.VERTICAL, 4, 34, 15); 
		slider.setOpaque(false);
	
		label1 	= new Label("  M U S T E R  ");
		label2	= new Label("----------  Klaus Wernicke  -----------");
		label3  = new Label("Einfluss der entfernten Farben");
		label1.setFont(font1);
		label2.setFont(font3);
		label3.setFont(font2);

		bStart = new JButton(start);
		bStart.setBackground(gruen);
		bStart.setSize(40, 60);
		bStart.addActionListener
		(new ActionListener()  // Start-Button
		{	public void actionPerformed(ActionEvent e)
			{	
				if(rechner.getLaufen())
				{
					rechner.setLaufen(false);
					bStart.setBackground(gruen);
					bStart.setText(start);
					EventQueue.invokeLater(new Runnable()
					{	public void run()
					    {rechner.neuStart();
					    }
					});
				}
				
				else 
				{
					rechner.setLaufen(true);
					bStart.setBackground(rot);
					bStart.setText(neu);	
				}
			}});
		
		slider.addChangeListener // Faktor
		(new ChangeListener()  
		{	public void stateChanged(ChangeEvent e)
	    	{	
				rechner.setFaktor((double)(slider.getValue())/10.);
	    	}});
	}	
	
	public void setLabel()
	{
		setLayout(new BorderLayout());
		panel1 = new Panel();
		panel1.setLayout(new GridLayout(0,1));
		panel1.add(label1);
		panel1.add(label2);
		panel1.add(label3);
		add("North", panel1);
		add("Center", slider);
		panel2 = new Panel();
		panel2.setLayout(new FlowLayout());
		panel2.add(bStart);
		add("South", panel2);
	}
}
 

Marco13

Top Contributor
Aaalso... Nicht Swing- und AWT Components mischen. Statt Panel und Label solltest du JPanel und JLabel verwenden. Statt Canvas sollte es ein JPanel sein, und dort sollte man paintComponent statt paint+update überschreiben:
Code:
@Override
public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    g.drawImage(img, rand, rand, this);
}

Das mit der EventQueue im actionPerformed macht so keinen Sinn, nimm das wieder raus.

Ein wichtiger Punkt könnte gewesen sein, dass in der MusterRechner bei "neuStart" am ende noch ein
[c]animation.aktualisieren();[/c]
gefehlt hat.

Aber das mit der MemoryImageSource ist sowieso etwas ... "unkonventionell" (ich denke, man könnte auch sagen: "veraltet"). Du solltest überlegen, das, was dort im Moment in der MemoryImageSource gespeichert wird, in ein BufferedImage zu packen. Das IST dann direkt das Bild, das auch gezeichnet wird. Aber das nur nebenbei.

Wenn's immernoch probleme gibt, kann man nochmal schauen...
 

Kanitrino

Bekanntes Mitglied
Ein wichtiger Punkt könnte gewesen sein, dass in der MusterRechner bei "neuStart" am ende noch ein
[c]animation.aktualisieren();[/c]gefehlt hat.
Das war der entscheidende Fehler. Allerdings ist das Problem damit nicht gelöst, es hält sich jetzt aber in einem erträglichen Rahmen. Ich werde mich wohl doch näher mit dem Event-Queue-Thema auseinandersetzen müssen.

Die "Hausaufgaben" mit dem einheitlichen Gebrauch von Swing-Komponenten habe ich gemacht.

Auch habe ich das Image durch ein BufferedImage ersetzt.

Das sieht nun so aus
Java:
// alt :

private void brettInPixels()
    {
        int farbe;
        int[]pixels;
        pixels = animation.getPixels();
        
        for(int y=0; y<anzHoehe; y++)
        for(int x=0; x<anzBreite; x++)
        {
            if(brettNeu[x][y]) farbe = blau;
            else               farbe = gelb;
 
            for(int a=0; a<karo; a++)
            for(int b=0; b<karo; b++)
                pixels[karo*x +a +(b+y*karo)*breitePix] = farbe;
        }   
        animation.setPixels(pixels);
    }   

// neu :


private void brettInPixels()
	{
		int farbe;
		
		for(int y=0; y<hoeheAnz; y++)
		for(int x=0; x<breiteAnz; x++)
		{
			if(brettNeu[x][y]) farbe = blau;
			else		 	 farbe = gelb;

			for(int a=0; a<karo; a++)
			for(int b=0; b<karo; b++)
				img.setRGB( x, y, farbe);
		}	
		animation.setImage(img);

// im Konstruktor :

img 			= new BufferedImage(breiteAnz*karo, hoeheAnz*karo, BufferedImage.TYPE_INT_RGB );

Ich brauche die Farben aus dem 2D-Array "brett[][] nun nicht mehr in einen 1D-Array "pixels[]" zu übertragen, den dann die "Rechner"- an die "Animation"-Klasse übergibt und der ihn dann mittels MemoryImageSource ins Image überträgt, sondern es wird direkt ins BufferedImage geschrieben - img.setRGB( x, y, farbe); - und dann das BuffImage-Objekt zum Zeichnen übergeben.
 

Marco13

Top Contributor
Falls das Problem noch auftritt, poste ggf. nochmal den aktuellen Code. Solche Synchronizationsprobleme sind da ein bißchen schwierig ("...bei mir geht's...") aber vielleicht sieht man ja noch was.
 

Kanitrino

Bekanntes Mitglied
Ich habe es immer noch nicht geschafft, das Problem zu lösen, deshalb möchte ich meine Frage mal allgemein stellen.

Problem : Beim Neustart bleibt oft ein Teil des alten Bildes stehen und wird nur teilweise durch das neue Bild ersetzt.

Verdacht : Das über ein Button-Event ausgelöste Neuzeichnen platzt mitten in die laufende (langwierige) Berechnung des alten Bildes hinein.

Mögliche Lösung : Das Button Event soll so lange warten, bis das alte Bild fertig gezeichnet ist.

Frage : Wie mache ich das grundsätzlich ?

Hier sind die beteiligten Code-Fragmente :

Java:
public class Rechner
....
       public void aktualisieren()
    {
        berechneBrett();
        brettInPixels();
     }
 
    private void brettInPixels()
    {
        ...        
        for(int y=0; y<anzHoehe; y++)
        for(int x=0; x<anzBreite; x++)
        {
            for(int a=0; a<karo; a++)                 // das dauert !
            for(int b=0; b<karo; b++)
                pixels[karo*x +a +(b+y*karo)*breitePix] = farbe;
        }   
        animation.setPixels(pixels);  // hier wird das Ergebnis an die Klasse 
                                        // "Animation" zum Zeichnen übergeben
    }

Hier haut der Action Listener der Klasse "Gui" rein :
Java:
bStart.addActionListener
(new ActionListener()  // Start-Button
{   public void actionPerformed(ActionEvent e)
    {   
        if(rechner.getLaufen())
        {
            rechner.setLaufen(false);
            rechner.neuStart();
        }
                
        else 
        {
            rechner.setLaufen(true);
         }
 }});

Bin ich auf der richtigen Spur ?
Wie geht das mit "invokeLater" oder wait()/ notify oder mit Prioritäten oder wie auch immer ?
Vielleicht könnte jemand in den Code eine Zeile reinschreiben (das wäre hilfreicher als endlose Links)
 

XHelp

Top Contributor
Du kannst ja auch mal mehr Code reinstellen. Das ganze zwar dennoch minimal, aber lauffähig, mit main-Methode etc. Dann kann man auch anhand deines Codes Vorschläge machen.
 

Marco13

Top Contributor
Hilfreicher als Codeschipsel, die wegen des Zusammenspiels von Threads wenig aussagen (zwei perfekt "richtige" Codestücke können problematisch sein, wenn sie von zwei verschiedenen Threads zu falschen Zeitpunkten aufgerufen werden) wäre (wieder einmal) ein KSKB.

Also... brettInPixels wird von einem Thread ausgeführt, und das actionPerformed vom EDT? Eine Möglichkeit wäre, dem Thread, der das Bild berechnet, von der actionPerformed aus nur eine Information zukommen zu lassen, die er dann selbst passend verarbeitet... (schwammig? Ja. Tja.)
 

Kanitrino

Bekanntes Mitglied
So, ihr habt es nicht anders gewollt, jetzt stelle ich das komplette Programm rein !

Das Phänomen wird - sofern kein Vorführeffekt auftritt - beim mehrmaligen Betätigen des Buttons sichtbar.

(Bei "Start" wird die Berechnung des Turing-Musters gestartet, bei "Random" wird mit einer neuen zufällige Anfangsverteilung neu angefangen.)

Java:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;

public class MusterSimulation extends Applikation_1
{
	private static final long serialVersionUID = 1L;
	private static int karo 		= 1;
	private static int breiteAnz 	= 300/karo;
	private static int hoeheAnz 	= 300/karo;
	Animation animation;
	MusterRechner rechner;
	MusterGui gui;
	protected static Dimension dim = new Dimension(185*breiteAnz*karo/100, 106*hoeheAnz*karo/100);
	Color hintergrund = new Color(210, 210, 230); //(120, 250, 210);

	public MusterSimulation()
	{
		super();
		msec 	  = 400;
		animation = new Animation(breiteAnz, hoeheAnz, karo, hintergrund);
		rechner	  = new MusterRechner(animation, this);
		gui		  = new MusterGui(this, rechner, hintergrund);
		super.setzeLayout((JPanel)animation, gui, dim, hintergrund);
		rechner.zufallsverteilung();
		laeuft = false;
//		starten();
		frame.setVisible(true);
	}

	public static void main(String arguments[])
    {
		new MusterSimulation();
    }

	public void run()
	{
		while(true){verzoegerung();
		while(laeuft)
    	{
    		rechner.aktualisieren();
    		animation.aktualisieren();
    		verzoegerung();
    	}
	}}
}

//************************************+

class MusterRechner
{
	protected Animation animation;
	protected MusterSimulation applet;
	protected BufferedImage img;
	protected int breiteAnz, hoeheAnz, karo;
	protected double faktor;
	boolean[][]brettAlt, brettNeu;
	private final int blau = 255 | 255 << 24;
	private final int gelb = 255 << 8 | 255 << 16 | 255 << 24;

	public MusterRechner(Animation animation, MusterSimulation applet)
	{
		this.animation 	= animation;
		this.applet 	= applet;
		breiteAnz		= animation.getBreiteAnz();
		hoeheAnz		= animation.getHoeheAnz();
		karo 			= animation.getKaro();
		img 			= new BufferedImage(breiteAnz*karo,
				hoeheAnz*karo, BufferedImage.TYPE_INT_RGB );
		brettAlt		= new boolean[breiteAnz][hoeheAnz];
		brettNeu		= new boolean[breiteAnz][hoeheAnz];
		brettLeeren();
		neuStart();
	}

	public void neuStart()
	{
		zufallsverteilung();
		brettInPixels();
		altern();
		animation.aktualisieren();
	}

	public void aktualisieren()
	{
		berechneBrett();
		brettInPixels();
		altern();
	}

	public void brettLeeren()
	{
		for(int y=0; y<hoeheAnz; y++)
		for(int x=0; x<breiteAnz; x++)
			brettNeu[x][y]=false;
	}

	public void zufallsverteilung()
	{
		double saat = Math.random()/2.;
		for(int y=0; y<hoeheAnz; y++)
		for(int x=0; x<breiteAnz; x++)
			if((x-breiteAnz/2)*(x-breiteAnz/2)
			  +(y-hoeheAnz/2)*(y-hoeheAnz/2)
			  < (breiteAnz*breiteAnz/6))
					brettNeu[x][y] = Math.random()<saat;
			else 	brettNeu[x][y] = false;
	}

	private void altern()
	{
		for(int y=0; y<hoeheAnz; y++)
		for(int x=0; x<breiteAnz; x++)
			brettAlt[x][y]	= brettNeu[x][y];
	}

	private void berechneBrett()
	{
		for(int y=0; y<hoeheAnz; y++)
		for(int x=0; x<breiteAnz; x++)
		{
			double wert1 =0;
			wert1 += (double)(zaehle(x, y, 0))*4;
			wert1 += (double) zaehle(x, y, 1);
			wert1 += (double)(zaehle(x, y, 2))/Math.sqrt(2.);
			wert1 += (double)(zaehle(x, y, 3))/2.;
			wert1 += (double)(zaehle(x, y, 4))/Math.sqrt(5.);

			double wert2 =0;

//			wert2 += (double)(zaehle(x, y, 5))/Math.sqrt(8.);
//			wert2 += (double)(zaehle(x, y, 6))/3.;
//			wert2 += (double)(zaehle(x, y, 7))/Math.sqrt(10.);
			wert2 += (double)(zaehle(x, y, 8))/Math.sqrt(13.);
			wert2 += (double)(zaehle(x, y, 9))/4.;
			wert2 += (double)(zaehle(x, y, 10))/Math.sqrt(17.);
			wert2 += (double)(zaehle(x, y, 11))/Math.sqrt(18.);
			wert2 += (double)(zaehle(x, y, 12))/Math.sqrt(20.);
			wert2 += (double)(zaehle(x, y, 13))/5.;
			wert2 += (double)(zaehle(x, y, 14))/Math.sqrt(26.);

			wert2 *= faktor;

			if(wert1 > wert2) brettNeu[x][y] = true;
			else 			  brettNeu[x][y] = false;
		}
	}

	private void brettInPixels()
	{
		int farbe;

		for(int y=0; y<hoeheAnz; y++)
		for(int x=0; x<breiteAnz; x++)
		{
			if(brettNeu[x][y]) farbe = blau;
			else		 	   farbe = gelb;

			for(int a=0; a<karo; a++)
			for(int b=0; b<karo; b++)
				img.setRGB( x, y, farbe);
		}
		animation.setImage(img);
	}

	private int zaehle(int x, int y, int nah)
	{
		int anz = 0;
		int x01, x02, x03, x04, x05, xx1, xx2, xx3, xx4, xx5,
			y01, y02, y03, y04, y05, yy1, yy2, yy3, yy4, yy5;

		x01 = (x-1+breiteAnz)%breiteAnz;
		xx1 = (x+1)%breiteAnz;
		y01 = (y-1+hoeheAnz)%hoeheAnz;
		yy1 = (y+1)%hoeheAnz;

		x02 = (x-2+breiteAnz)%breiteAnz;
		xx2 = (x+2)%breiteAnz;
		y02 = (y-2+hoeheAnz)%hoeheAnz;
		yy2 = (y+2)%hoeheAnz;

		x03 = (x-3+breiteAnz)%breiteAnz;
		xx3 = (x+3)%breiteAnz;
		y03 = (y-3+hoeheAnz)%hoeheAnz;
		yy3 = (y+3)%hoeheAnz;

		x04 = (x-4+breiteAnz)%breiteAnz;
		xx4 = (x+4)%breiteAnz;
		y04 = (y-4+hoeheAnz)%hoeheAnz;
		yy4 = (y+4)%hoeheAnz;

		x05 = (x-5+breiteAnz)%breiteAnz;
		xx5 = (x+5)%breiteAnz;
		y05 = (y-5+hoeheAnz)%hoeheAnz;
		yy5 = (y+5)%hoeheAnz;

		if(nah==0)
		{
			if(brettAlt[x][y]) anz++;
		}

		else if(nah==1)
		{
			if(brettAlt[x01][y]) anz++;
			if(brettAlt[xx1][y]) anz++;
			if(brettAlt[x][y01]) anz++;
			if(brettAlt[x][yy1]) anz++;
		}
		else if(nah==2)
		{
			if(brettAlt[x01][y01]) anz++;
			if(brettAlt[xx1][y01]) anz++;
			if(brettAlt[x01][yy1]) anz++;
			if(brettAlt[xx1][yy1]) anz++;
		}

		else if(nah==3)
		{
			if(brettAlt[x02][y]) anz++;
			if(brettAlt[xx2][y]) anz++;
			if(brettAlt[x][y02]) anz++;
			if(brettAlt[x][yy2]) anz++;
		}

		else if(nah==4)
		{
			if(brettAlt[x02][y01]) anz++;
			if(brettAlt[x02][yy1]) anz++;
			if(brettAlt[x01][y02]) anz++;
			if(brettAlt[x01][yy2]) anz++;

			if(brettAlt[xx1][y02]) anz++;
			if(brettAlt[xx1][yy2]) anz++;
			if(brettAlt[xx2][y01]) anz++;
			if(brettAlt[xx2][yy1]) anz++;
		}

		else if(nah==5)
		{
			if(brettAlt[x02][y02]) anz++;
			if(brettAlt[xx2][y02]) anz++;
			if(brettAlt[x02][yy2]) anz++;
			if(brettAlt[xx2][yy2]) anz++;
		}

		else if (nah==6)
		{
			if(brettAlt[x][y03]) anz++;
			if(brettAlt[x][yy3]) anz++;
			if(brettAlt[x03][y]) anz++;
			if(brettAlt[x03][y]) anz++;
		}

		else if(nah==7)
		{
			if(brettAlt[x03][y01]) anz++;
			if(brettAlt[x03][yy1]) anz++;
			if(brettAlt[x01][y03]) anz++;
			if(brettAlt[x01][yy3]) anz++;

			if(brettAlt[xx1][y03]) anz++;
			if(brettAlt[xx1][yy3]) anz++;
			if(brettAlt[xx3][y01]) anz++;
			if(brettAlt[xx3][yy1]) anz++;
		}

		else if(nah==8)
		{
			if(brettAlt[x03][y02]) anz++;
			if(brettAlt[x03][yy2]) anz++;
			if(brettAlt[x02][y03]) anz++;
			if(brettAlt[x02][yy3]) anz++;

			if(brettAlt[xx2][y03]) anz++;
			if(brettAlt[xx2][yy3]) anz++;
			if(brettAlt[xx3][y02]) anz++;
			if(brettAlt[xx3][yy2]) anz++;
		}

		else if(nah==9)
		{
			if(brettAlt[x][y04]) anz++;
			if(brettAlt[x][yy4]) anz++;
			if(brettAlt[x04][y]) anz++;
			if(brettAlt[xx4][y]) anz++;
		}

		else if(nah==10)
		{
			if(brettAlt[x01][y04]) anz++;
			if(brettAlt[x01][yy4]) anz++;
			if(brettAlt[x04][y01]) anz++;
			if(brettAlt[x04][yy1]) anz++;

			if(brettAlt[xx1][y04]) anz++;
			if(brettAlt[xx1][yy4]) anz++;
			if(brettAlt[xx4][y01]) anz++;
			if(brettAlt[xx4][yy1]) anz++;
		}

		else if(nah==11)
		{
			if(brettAlt[x03][y03]) anz++;
			if(brettAlt[x03][yy3]) anz++;
			if(brettAlt[xx3][y03]) anz++;
			if(brettAlt[xx3][yy3]) anz++;
		}

		else if(nah==12)
		{
			if(brettAlt[x02][y04]) anz++;
			if(brettAlt[x02][yy4]) anz++;
			if(brettAlt[x04][y02]) anz++;
			if(brettAlt[x04][yy2]) anz++;

			if(brettAlt[xx2][y04]) anz++;
			if(brettAlt[xx2][yy4]) anz++;
			if(brettAlt[xx4][y02]) anz++;
			if(brettAlt[xx4][yy2]) anz++;
		}

		else if(nah==13)
		{
			if(brettAlt[x03][y04]) anz++;
			if(brettAlt[x03][yy4]) anz++;
			if(brettAlt[x04][y03]) anz++;
			if(brettAlt[x04][yy3]) anz++;

			if(brettAlt[xx3][y04]) anz++;
			if(brettAlt[xx3][yy4]) anz++;
			if(brettAlt[xx4][y03]) anz++;
			if(brettAlt[xx4][yy3]) anz++;

			if(brettAlt[x][y05]) anz++;
			if(brettAlt[x][yy5]) anz++;
			if(brettAlt[x05][y]) anz++;
			if(brettAlt[xx5][y]) anz++;
		}

		else if(nah==14)
		{
			if(brettAlt[x01][y05]) anz++;
			if(brettAlt[x01][yy5]) anz++;
			if(brettAlt[x05][y01]) anz++;
			if(brettAlt[x05][yy1]) anz++;

			if(brettAlt[xx1][y05]) anz++;
			if(brettAlt[xx1][yy5]) anz++;
			if(brettAlt[xx5][y01]) anz++;
			if(brettAlt[xx5][yy1]) anz++;
		}
		else anz= -1;
		return anz;
	}

	public void setFaktor(double faktor)
	{
		this.faktor = faktor;
	}
}

//*****************************


class Animation extends JPanel
{
	private static final long serialVersionUID = 1L;
	protected int breiteAnz, hoeheAnz, karo, breitePix , hoehePix, rand=10;
	protected BufferedImage img;
	Color hintergrund;

	public Animation(int breiteAnz, int hoeheAnz, int karo, Color hintergrund)
	{
		this.breiteAnz = breiteAnz;
		this.hoeheAnz   = hoeheAnz;
		this.karo 		= karo;
		breitePix		= breiteAnz*karo;
		hoehePix		= hoeheAnz*karo;
		this.hintergrund= hintergrund;
	    setBackground(hintergrund);
	    aktualisieren();
	}

	 public void aktualisieren()
	 {
		 repaint();
	 }

		public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		g.drawImage(img, rand, rand, this);
	}

	public void setImage(BufferedImage img)
	{
		this.img = img;
	}

	public int getBreiteAnz()
	{
		return breiteAnz;
	}

	public int getHoeheAnz()
	{
		return hoeheAnz;
	}

	public int getKaro()
	{
		return karo;
	}

	public Dimension getPreferredSize()
	{	return new Dimension(breitePix+2*rand, hoehePix+2*rand);}
}

//*********************

class MusterGui extends JPanel
{
	private static final long serialVersionUID = 1L;
	MusterSimulation applet;
	MusterRechner rechner;
	JButton bStart;
	JSlider slider;
   	JLabel label1, label2, label3;
   	String start, neu;
	Font font1, font2, font3;
	JPanel panel1, panel2, panel3, panel4;
	Color rot, gruen;

	public MusterGui(MusterSimulation applet, MusterRechner rechner,
			Color hintergrund)
	{
		this.applet	 = applet;
		this.rechner = rechner;
		start = "   S T A R T    ";
		neu   = "  R A N D O M  ";
		gruen = new Color(31, 168, 23); //(120, 250, 110);
		rot = new Color(250, 120, 75);
		setKomponenten();
		setLabel();
		rechner.setFaktor((double)(slider.getValue())/10.);
		setBackground(hintergrund);
//		setLookAndFeel(4);
	}

		public void setLookAndFeel(int laf)
		{
			String look = " ";
			if 		(laf == 1) look = "javax.swing.plaf.metal.MetalLookAndFeel";
			else if (laf == 2) look = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
			else if (laf == 3) look = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
			else if (laf == 4) look = "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel";

			try
			{
				UIManager.setLookAndFeel( look );
			}
			catch(IllegalAccessException iae){}
			catch(UnsupportedLookAndFeelException ulaf){}
			catch(ClassNotFoundException cnfe){}
			catch(InstantiationException ie){}
		}

	public void setKomponenten()
	{
		font1	= new Font("VERDANA",Font.BOLD,26);
		font2	= new Font("VERDANA",Font.PLAIN,12);
		font3	= new Font("VERDANA",Font.PLAIN,10);

		slider = new JSlider(JSlider.VERTICAL, 4, 34, 15);
		slider.setOpaque(false);

		label1 	= new JLabel(" M U S T E R ");
		label2	= new JLabel("--------  Klaus Wernicke  ---------");
		label3  = new JLabel("Einfluss der entfernten Farben");
		label1.setFont(font1);
		label2.setFont(font3);
		label3.setFont(font2);

		bStart = new JButton(start);
		bStart.setForeground(gruen);
		bStart.setSize(40, 60);
		bStart.addActionListener
		(new ActionListener()  // Start-Button
		{	public void actionPerformed(ActionEvent e)
			{
				if(applet.getLaufen())
				{
					bStart.setForeground(gruen);
					bStart.setText(start);
					applet.setLaufen(false);
					rechner.neuStart();
				}

				else
				{
					bStart.setForeground(rot);
					bStart.setText(neu);
					applet.setLaufen(true);
					applet.starten();
				}
			}});

		slider.addChangeListener // Faktor
		(new ChangeListener()
		{	public void stateChanged(ChangeEvent e)
	    	{
				rechner.setFaktor((double)(slider.getValue())/10.);
	    	}});
	}

	public void setLabel()
	{
		setLayout(new BorderLayout());
		panel1 = new JPanel();
		panel1.setOpaque(false);
		panel1.setLayout(new GridLayout(0,1));
		panel1.add(label1);
		panel1.add(label2);
		panel1.add(label3);
		add("North", panel1);
		add("Center", slider);
		panel2 = new JPanel();
		panel2.setOpaque(false);
		panel2.setLayout(new FlowLayout());
		panel2.add(bStart);
		add("South", panel2);
	}
}

//*****************************

class Applikation_1 extends JPanel implements Runnable
{
	private static final long serialVersionUID = 1L;
	protected JFrame frame;
	protected JPanel panel, panelAni;
	protected boolean laeuft;
	protected static long msec;
	protected Thread running;
	protected int breiteAnz, hoeheAnz, karo, breitePix, hoehePix, hoehePopPix;

	public void run(){}

	public Applikation_1()
    {
		frame = new JFrame("*");
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLayout(new GridBagLayout());
		frame.add(this);
		running = new Thread(this);
    }

	protected void setzeLayout(JPanel animation, JPanel gui, Dimension dim, Color hintergrund)
	{
		panel = new JPanel();
		panel.setPreferredSize(dim);
		this.add(panel);
		panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		panel.setLayout(new BorderLayout());
		panel.setBackground(hintergrund);
		panel.add("East", gui);
		panel.add("Center", animation);
	}

	public void setLaufen(boolean laufen)
	{
		laeuft = laufen;
	}

	public boolean getLaufen()
	{
		return laeuft;
	}

	public void starten()
	{	if (running == null);
		{	running = new Thread(this);
			running.start();
	}	}

	public void stop()
	{	running = null;
	}

	public void verzoegerung()
	{	try {Thread.sleep (msec);}
		catch(Exception e){}
	}
}
 

Marco13

Top Contributor
Ist ja OK :) Du hattest es ja in einem früheren Stand schonmal gepostet. Das ist gut, so kann man es einfach rauskopieren, starten, und sehen, dass....

(mit der Hand an den Kopf patschen in
3
...
2
...
1
...)

... bei applet.starten(); jedes mal ein neuer Thread erzeugt wird! Hab's gerade mal rausgenommen, dann trat das Problem anscheindend nicht mehr auf (was aber noch keine Garantie ist ... falls das nicht reicht, sag' nochmal bescheid...)
 

Kanitrino

Bekanntes Mitglied
Hallo Marco,

Vielen Dank erst Mal !

Aber... es bleibt höchst befremdlich :
1. Das Problem ist wesentlich besser (wie schon nach Deinem Tipp, nicht awt & swing zu mischen), aber ich schaffe immer noch, es zu erzeugen. Offenbar gibt es also nicht "ein" Problem. Nun würd' es mich eigentlich nicht mehr stören, aber mich stört, dass ich es so wenig verstehe. Wie ich bereits erfahren musste (http://www.java-forum.org/allgemeine-java-themen/105543-starten-threads.html)), ist das mit den Threads offenbar alles Lug & Trug.

2. Meine starten()-Methode lautet
Java:
 public void starten()
    {   if (running == null);
        {   running = new Thread(this);
            running.start();
    }   }
Eigentlich sollte es also nicht möglich sein, mehrere Threads zu starten. Ist das also auch anders als es sein sollte ?
(Wie kann man eigentlich festsellen, dass zu viele Threads laufen ?)

3. War ich mit meinem Threadtitel auf der falschen Spur ? Ist es kein Problem, dass eine Button-Action in eine laufende Berechnung einbricht ?

4. Es bleibt also schwierig...
 

Marco13

Top Contributor
2. Meine starten()-Methode lautet
Java:
 public void starten()
    {   if (running == null);
        {   running = new Thread(this);
            running.start();
    }   }
Eigentlich sollte es also nicht möglich sein, mehrere Threads zu starten. Ist das also auch anders als es sein sollte ?
(Wie kann man eigentlich festsellen, dass zu viele Threads laufen ?)

.... aaaaa :shock: Viel subtiler: Da steht ein ";" hinter der if-Abfrage (hab' ich aber auch eben erst gesehen, auf der verzweifelten suche nach der Stelle, wo "stop" aufgerufen wird).

Erst dachte ich, es wäre ein Mißverständnis deinerseits:
Thread t = new Thread(runnable);
t.start();
t = null; // Hier lauft der Thread noch weiter!
Und der läft "ewig", wenn in der run()-Methode ein "while(true)" außenrum steht.

Man kann sich anschauen, wie viele Threads laufen (und was sie machen) mit der "jvisualvm" - die ist beim JDK im /bin-Unterordner.

Ansonsten schau ich morgen nochmal, wie gesagt, es kann sein, dass da immernoch ein "synchronisationsproblem" besteht...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
berserkerdq2 Habe ich die Aufgabe richtig gelöst? Java Basics - Anfänger-Themen 3
berserkerdq2 Habe ein Spiel entwickelt, dass immer in der 4 Runde einen cast-Fehler erhält Java Basics - Anfänger-Themen 3
berserkerdq2 Habe eine Klasse, welche public ist, diese hat eine public Methode, die nicht static ist. Wenn ich nun versuche aufzurufen Probleme? Java Basics - Anfänger-Themen 8
berserkerdq2 Habe zwei exceptions, welche ist ein Kommunikationsfehler und welche ein Ausgabefehler? Java Basics - Anfänger-Themen 4
berserkerdq2 Wann soll ich den Stream schließen, wenn ich das in einer Methode habe? Java Basics - Anfänger-Themen 8
O Ich habe einen String und soll mit matches schauen, ob ein Buchstabe zu einer geraden ANzahl im String vorkommt, wie soll das gehen? Java Basics - Anfänger-Themen 7
EchtKeineAhnungManchmal hallo habe ein Problem mit einer Datei -> (Zugriff verweigert) Java Basics - Anfänger-Themen 4
Aqtox Hallo ich muss für die Schule ein Wuerfell Duell erstellen jedoch habe ich ein fehler Java Basics - Anfänger-Themen 4
I DecimalFormat in Zahlenformat für Währung, habe 7,99, bekomme aber 7 Java Basics - Anfänger-Themen 4
M Was habe ich hier falsch, dass wenn ich z.B.: 11 eingebe mir false zurück gegeben wird? Java Basics - Anfänger-Themen 2
Kapfski Was habe ich falsch gemacht? Hilfe! Java Basics - Anfänger-Themen 17
T Ich habe eine Variabel die nicht Methoden übergreifend ist. Kann mir jemand Helfen :) Java Basics - Anfänger-Themen 5
I Ich habe ein Problem Java Basics - Anfänger-Themen 3
F Habe ein problem mit dem ActionListener Java Basics - Anfänger-Themen 3
I wieder mit einer Umwandelung habe ich Problem (diesmal von char Array zu char) Java Basics - Anfänger-Themen 1
A Ich habe das Gefühl etwas grundlegendes falsch zu machen Java Basics - Anfänger-Themen 6
V Erste Schritte Habe Fragen zu der For und While Schleife als auch Inkrement und Dekrement Java Basics - Anfänger-Themen 4
E Habe ein Problem Java Basics - Anfänger-Themen 10
JavaNewbie2.0 Habe ein frage wie man etwas macht. Java Basics - Anfänger-Themen 13
A Methoden Habe ein Problem bei folgender Programmierung Java Basics - Anfänger-Themen 15
Z Was habe ich davon mit einem Datentyp verschiedene Instanzen zu haben? Java Basics - Anfänger-Themen 6
B Erste Schritte Way of life ohne import - Habe Beispiel, macht Unfug Java Basics - Anfänger-Themen 21
J Java: Was habe ich falsch gemacht? Java Basics - Anfänger-Themen 4
Thallius String und \n. Habe wohl gerade Brett vorm Kopf Java Basics - Anfänger-Themen 13
G Umgebungsvariable Hallo Ich habe ein Problem mit der Umgv Java Basics - Anfänger-Themen 9
F String.replaceAll() funktioniert nicht richtig oder habe ich den falschen Regex?? Java Basics - Anfänger-Themen 3
C JDK installieren Habe ein Problem bei Java install Java Basics - Anfänger-Themen 4
J Habe problem mit Java Java Basics - Anfänger-Themen 2
S Habe mist gebaut.. ^^ Java Basics - Anfänger-Themen 4
I Habe keine Idee was ich als Anfänger programmieren kann. Java Basics - Anfänger-Themen 4
B Warum kommt immer die 0 als Ergebnis? Was habe ich falsch gemacht? Java Basics - Anfänger-Themen 18
E Habe java. Datei wie ausführen ? Java Basics - Anfänger-Themen 9
B Habe einen Fehler Java Basics - Anfänger-Themen 3
G Habe ein Problem mit syn-Editor ( beim compilieren) Java Basics - Anfänger-Themen 4
U Habe meine .class files gelöscht. Java Basics - Anfänger-Themen 3
S Taschenrechner programmieren und habe null Ahnung Java Basics - Anfänger-Themen 22
S Ich habe ein kleines Problem mit meinem Übungsprogramm Java Basics - Anfänger-Themen 7
G habe ein Catch problem Java Basics - Anfänger-Themen 7
X Habe Set, möchte List Java Basics - Anfänger-Themen 3
W Applet starten - ich habe keine ahnung Java Basics - Anfänger-Themen 17
G Habe bei String kein split()? Java Basics - Anfänger-Themen 7
K Brauche nur Tipps Leute habe keine plan wie ich dass machen Java Basics - Anfänger-Themen 4
R Habe ein Problem und eine Frage Java Basics - Anfänger-Themen 19
P Habe da ein Problem mit Arrays! Bitte um Hilfe Java Basics - Anfänger-Themen 2
A Gleichungssystem: Ich habe es probiert! Java Basics - Anfänger-Themen 4
H habe keine main Java Basics - Anfänger-Themen 9
J Habe gerade erst mit Java begonnen - Frage zu JTabbedPane Java Basics - Anfänger-Themen 3
ven000m Rauten "Stern" zeichnen, hälfte habe ich zweite? Java Basics - Anfänger-Themen 2
G Habe Fragen zu der Programmierung eines Matheprogramms Java Basics - Anfänger-Themen 5
T HILFE! Ich habe keinen Plan mehr! Java Basics - Anfänger-Themen 16
M Habe ein Problem mit dem Konstruktor!Wer kann helfen? Java Basics - Anfänger-Themen 15
Z Warum habe ich eine ArrayIndexOutOfBoundsException? Java Basics - Anfänger-Themen 2
E Threads Synchronisationsproblem Java Basics - Anfänger-Themen 5
T servlet synchronisationsproblem Java Basics - Anfänger-Themen 4

Ähnliche Java Themen

Neue Themen


Oben