Hallo liebe Community,
ich habe mich hier angemeldet, weil ich ein Problem mit einem Programm habe:
Es wird die Mandelbrotmenge gezeichnet, dazu wird ein Iterationsvorgang verwendet, mit dem eine Reihe Zahlen überprüft wird. Je nach Ergebnis soll ein Punkt im JPanel gezeichnet werden. Mein Problem ist, dass der repaint()-Aufruf zu oft hintereinander aufgerufen wird, und so nicht jeder Punkt gezeichnet wird.
Deshalb habe ich die entsprechende Methode mit Thread.sleep(10); "ausgebremst".
Zufrieden bin ich mit dieser Lösung nicht, und würde mich über Hilfe freuen
Hier der Code:
Klasse Frame2
und hier noch der Code der Klasse MENGE:
Die iterieren(..)-Methode dient nur zur Vollständigkeit.
Wie könnte man das Darstellungsproblem aller Punkte auf dem Bildschirm lösen?
Ich sage schon mal vielen Dank
ich habe mich hier angemeldet, weil ich ein Problem mit einem Programm habe:
Es wird die Mandelbrotmenge gezeichnet, dazu wird ein Iterationsvorgang verwendet, mit dem eine Reihe Zahlen überprüft wird. Je nach Ergebnis soll ein Punkt im JPanel gezeichnet werden. Mein Problem ist, dass der repaint()-Aufruf zu oft hintereinander aufgerufen wird, und so nicht jeder Punkt gezeichnet wird.
Deshalb habe ich die entsprechende Methode mit Thread.sleep(10); "ausgebremst".
Zufrieden bin ich mit dieser Lösung nicht, und würde mich über Hilfe freuen
Hier der Code:
Klasse Frame2
Java:
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.event.*;
import java.lang.Math.*;
public class Frame2 extends Thread{
JFrame fenster;
Menge menge;
/**
* Konstruktor
*/
public Frame2 (){
fenster = new JFrame ("Mandelbrotmenge");
fenster.setBackground(Color.white);
menge = new Menge();
fenster.add(menge);
//menueErzeugen();
fenster.setSize(600,600);
fenster.setVisible(true);
}
/**
* Mit dieser Methode wird mittels der beiden for-Schleifen eine Reihe komplexer Zahlen in Schritten von 0.01 durchgegangen.
* Dies wird mit den Zählvariablen t(Realteil) und u (Imaginärteil) umgesetzt, die dann der iterieren(..)-Methode zur Prüfung übergeben werden.
*
*/
public void punkteEinfuegen (){
//fuer die Addition komplexer Zahlen gilt: c + w = (a,ib)+(c,id)=(a+c,ib+id);
//fuer die Multiplikation komplexer Zahlen gilt: c+w = (a,b)*(c,d) = (a*c-ib*id,a*id+ib*c);
//Zählvariablen
double t =-2.00; //Real
double u = -1.00; //Imag
//Schleifen zum durchgang aller Zahlen im Bereich von re=[-2;1] und im = [-1i;1i]
for (int re = -200; re < 100; re++){
u= -1.00;
for(int im= -100; im < 100; im++) {
switch(iterieren(t,u)){ //Der Methode iterieren(...) wird Real- und Imaginärteil übergeben; je nach erhaltenen Rückgabewert soll eine Aktion ausgewählt werden:
case 1: menge.punktEinfuegen(t,u,Color.blue); // Falls 1 zurückgegeben wird, ist die Zahl ein Element der Mandelbrotmenge, und kann somit blau gezeichnet werden.
break;
case 2: menge.punktEinfuegen(t,u,Color.pink); // Für jede Zahl >1 liegt die Zahl nicht in der Mandelbrotmenge und kann somit in einer anderen Farbe gezeichnet werden.
break; // |
case 3: menge.punktEinfuegen(t,u,Color.magenta); // | Farbabstufungen
break; // \/
case 4: menge.punktEinfuegen(t,u,Color.red);
break;
case 5: menge.punktEinfuegen(t,u,Color.orange);
break;
case 6: menge.punktEinfuegen(t,u,Color.yellow);
break;
}
try{ // Das ist meine primitiv-Lösung damit alle Punkte auch angezeigt werden. Durch die 10-millisekündliche Pausierung
Thread.sleep(10); // ist die Bildschirmausgabe größtenteils fehlerfrei. Allerdings verlangsamt sich das Programm dadurch sehr.
}catch (InterruptedException e) {} // Für eine andere Lösung wäre ich sehr dankbar.
u = u + 0.01;
}
t = t +0.01;
}
}
/**
* Diese Mehthode prüft eine übergebene Zahl (Realteil und Imaginärteil), ob sie Element der Mandelbrotmenge ist.
* Dies wird mit den Zählvariablen t und u umgesetzt.
*
* @param cre Realteil einer mit der Iterationsformel zu prüfenden Zahl
* @param cim Imaginärteil einer mit der Iterationsformel zu prüfenden Zahl
* @return 1 falls die übergebene Zahl (cre,cim) Element der Mandelbrotmenge ist; eine Zahl größer eins wenn die Zahl kein Element der Mandelbrotmenge ist.
*/
private int iterieren(double cre, double cim){
double zre = 0; // zre und zim wird für die Iterationsvorschrift benötigt (Zahl Z auf dem Skript)
double zim = 0;
int iteration = 0; // Die Variable der for-Schleife wird hier bereits angelegt, um den Gültigkeitsbereich dieser auf die ganze Methode zu erweitern.
double betrag = 10; // Hier wird der Betrag von Z nach jedem Schleifendruchlauf gespeichert. Aus vorher genanntem Grund wird diese ebenfalls hier angelegt.
// Die Zahl 10 ist beispielhaft gewählt (größer als zwei), falls in der for-Schleife betrag nicht überschrieben werden sollte, muss dennoch ein Wert vor-
// handen sein.
for(iteration = 0; iteration<25; iteration++){
double temp = zre;
// zum Rechnen mit komplexen Zahlen werden diese immer als Paar zweier Zahlen getrennt gespeichert, so auch hier:
// Formel:
zre = (zre*zre-zim*zim)+ (cre);
zim = (2*zim*temp)+(cim);
// Nach jedem Durchlauf soll noch geprüft werden, ob der Iterationsvorgang nicht schon früher abgebrochen werden kann. Dazu wird der Betrag der Zahl Z = (zre,zim)
// berechnet.
betrag = Math.sqrt((zre*zre) + (zim*zim));
//Uebersteigt der Betrag von Z den Wert 2, so kann laut Skript abgebrochen werden
if(betrag>=2){
break;
}
}
if(iteration == 25 && betrag <2){
return 1; // ist nach 25 Iterationsvorgängen noch nicht abgeborchen worden (also betrag <2), so wird 1 zurückgegeben.
} else {
switch (iteration) {
case 24: return 2; // Bei den sonstigen Fällen wird eine Zahl größer 1 zurückgegeben. Die Staffelung hier ist beliebig gewählt und dient zur Darstellung
// mit verschiedenen Farben.
case 23: return 2;
case 22: return 2;
case 21: return 2;
case 20: return 2;
case 19: return 3;
case 18: return 3;
case 17: return 3;
case 16: return 3;
case 15: return 3;
case 14: return 4;
case 13: return 4;
case 12: return 4;
case 11: return 4;
case 10: return 4;
case 9: return 5;
case 8: return 5;
case 7: return 5;
case 6: return 5;
case 5: return 5;
case 4: return 6;
case 3: return 6;
case 2: return 6;
case 1: return 6;
case 0: return 6;
}
}
return 6; // falls ein oben genannter Fall in der if-Abfrage/switch-Anweisung nicht eintritt
}
}
und hier noch der Code der Klasse MENGE:
Java:
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
public class Menge extends JPanel {
private int x;
private int y;
private Color farbe;
/**
* Konstruktor
*/
public Menge(){
x = 0;
y = 0;
farbe = Color.black; // wird hier schwarz gesetzt, da unten in paint(Graphics g) bereits ein Punkt in (0|0) gezeichnet wird.
}
/**
* Diese Mehthode fügt eine Zahl(Realteil und Imaginärteil) als farbigen Punkt ein. Die anzugebenden Koordinaten sind die, die im gezeichneten KOSY angezeigt werden.
* Diese Koordinaten werden von dieser Methode in jene umgerechnet, die das Java-KOSY benötigt (siehe unten).
*
* @param x Realteil einer Zahl
* @param y Imaginärteil einer Zahl
* @param farbe Farbe des Punktes, der gezeichnet werden soll.
*/
public void punktEinfuegen(double x, double y, Color farbe) {
//Umrechen der üblichen Koordinaten in diejenigen, die zur Darstellung benötigt werden (Ursprung KOSY (340|280); 1 LE im KOSY sind 100 LE in Java)
this.x = (int) (340 + x*100); // 100 entspr. 1 LE, deswegen x*100; bei 340 ist x = 0, also +340
this.y = (int) (280 - y*100); // 100 entspr. 1 LE, deswegen y*100; bei 280 ist y = 0, aber diese wird nach unten hin größer, also -240
this.farbe = farbe;
repaint();
}
/**
* Diese Mehthode zeichnet KOSY-Achsen (inkl. Beschriftungen), sowie einen Punkt mit den Koordinaten (x|y).
*
*/
public void paint (Graphics g) {
Graphics2D g2d = (Graphics2D) g;
//Farbe
g2d.setColor(Color.black);
//Achsen
g2d.drawLine(340,0,340,600);
g2d.drawLine(0,280,600,280);
//KOSY Ursprung: (340|280)
//Re-Achse Zahlen
g2d.drawLine(440,275,440,285);
g2d.drawString("1",440,300);
g2d.drawLine(240,275,240,285);
g2d.drawString("-1",240,300);
g2d.drawLine(140,275,140,285);
g2d.drawString("-2",140,300);
//Pfeilspitze und Achsenbeschriftung
g2d.drawLine(545,275,550,280);
g2d.drawLine(545,285,550,280);
g2d.drawString("Re",560,300);
g2d.drawLine(335,5,340,0);
g2d.drawLine(345,5,340,0);
g2d.drawString("Im",350,15);
//Im-Achse Zahlen
g2d.drawLine(335,180,345,180);
g2d.drawString("1i",350,190);
g2d.drawLine(335,380,345,380);
g2d.drawString("-1i",350,390);
// Zeichnet Punkt. Wird benötigt, um die einzelnen Punkte der Mandelbrotmenge einzuzeichnen.
g2d.setColor(farbe);
g2d.drawLine(x,y,x,y);
}
}
Die iterieren(..)-Methode dient nur zur Vollständigkeit.
Wie könnte man das Darstellungsproblem aller Punkte auf dem Bildschirm lösen?
Ich sage schon mal vielen Dank