Slyh: Darstellungsproblem mit Grafik

Beitrag lesen

Hallo Christoph und Daniel,

von mir gibt es jetzt auch noch eine etwas stärker veränderte Version auf's
Auge:

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Image;
import java.awt.Color;
import java.applet.Applet;

public class Julia extends Applet implements Runnable {

Thread   drawThread = null;

Image    backgroundImage;
 Graphics backgroundGraphics;

int    h;
 int    b;

int    tiefe = 16;
 double o     = 1.0;
 double u     = -1.0;
 double l     = -1.75;
 double r     = 1.75;
 double c_x   = -0.75543;
 double c_y   = 0.12301;

boolean running = false;

byte    map[][];

public void init() {
  b = getSize().width;
  h = getSize().height;
  backgroundImage    = createImage(b, h);
  backgroundGraphics = backgroundImage.getGraphics();

backgroundGraphics.setColor(new Color(238, 238, 238));
  backgroundGraphics.fillRect(0, 0, b, h);
 }

public void stop() {
  running = false;
 }

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

int tempx(double x) {
  return (int)((double)(x - l) / (r - l) * b);
 }

int tempy(double y) {
  return (int)((double)(y - o) / (u - o) * h);
 }

public void paint(Graphics g) {
  g.drawImage(backgroundImage, 0, 0, this);
 }

public void update(Graphics g) {
  paint(g);
 }

public void run() {
  map = new byte[getSize().width][getSize().height];
  zeichnen(1.0, 1.0);
  repaint();
 }

void zeichnen(double x, double y) {

double r;
  double neux;
  double neuy;
  int    num;

while (running == false) {
   try {
    Thread.sleep(1);
   } catch (InterruptedException e) {
   }
  }

int xtmp = tempx(x);
  int ytmp = tempy(y);

map[xtmp][ytmp]++;
  backgroundGraphics.setColor(new Color(0, 0, 160));
  backgroundGraphics.drawLine(xtmp, ytmp, xtmp, ytmp);
  repaint();

if (map[xtmp][ytmp] < tiefe) {
   x -= c_x; y -= c_y;
   r = Math.sqrt(x*x + y*y);

num = (y>0)?1:(y<0)?-1:0;
   neux = Math.sqrt((r + x) / 2);
   neuy = Math.sqrt((r - x) / 2) * num;

zeichnen(neux, neuy);
   zeichnen(-neux, -neuy);

}
 }
}

Hier wird jetzt - wie bei Daniel schon - immer in ein Image geschrieben und
dann dieses Image auf der Zeichenfläche des Applets dargestellt.
Das große Manko an dieser Lösung ist, daß nach jedem gezeichneten Pixel immer
sofort "repaint()" aufgerufen wird, was die Sache nicht gerade sehr performant
macht. Eine Möglichkeit das zu verbessern, wäre z.B. repaint() nur jedes zehnte
oder fünzigste mal aufzurufen.
Eine andere Möglichkeit bestände darin, sowohl den Pixel in das Image als auch
auf die Applet-Zeichenfläche zu zeichnen. Ein repaint() wäre dann nicht mehr
notwendig. Paint() würde nur noch dann aufgerufen werden, wenn ein Teil der
Applet-Zeichenfläche neu gezeichnet werden muß, weil sie z.B. durch ein anderes
Fenster zerstört wurde. Die paint()-Methode würde dann wie jetzt schon einfach
das Image auf die Zeichenfläche malen. Bei dieser Möglichkeit der Realisierung
könnte es aber zu Inkonsistenzen in der Darstellung kommen, wenn gleichzeitig
das Bild wie auch der Pixel auf die Applet-Zeichenfläche gezeichnet wird.
Hier müßte dann sychronisiert werden.

Aber ich denke mal, daß dir, Cristoph, das so schon reichen wird.

Das Flimmern bei Daniels Lösung kommt übrigens daher, daß beim Aufruf von
repaint() die Methode update() aufgerufen wird, die zuerst die komplette
Zeichenfläche löscht und erst dann paint() aufruft. Durch das Löschen
entsteht das genannte Flimmern. Die Lösung besteht darin, die update()-Methode
zu überschreiben und darin nur paint() aufzurufen. (So oder so ähnlich ist
das auch in der API-Dokumentation zu repaint() und update() nachzulesen.)

Gruß
Slyh

PS: Den vollständigen Code poste ich übrigens nur der Gewissheit wegen, daß
Christoph nicht auf die Lösung, sondern auf das Verständnis aus ist. Fertige
Lösungen gibt es von mir sonst nicht.