Christoph Schnauß: Darstellungsproblem mit Grafik

guten Abend Forum ;-)

ich habe an einem kleinen (2KB) Applet herumgebastelt, das ich zu dekorativen Zwecken einsetzen möchte. Es soll nichts anderes tun, als eine fraktale Grafik (Juliamenge) zeichnen  -  das tut es auch.

Aber: wenn die Seite, in der es enthalten ist, gescrollt wird und das Appelt damit aus dem Anzeigebereich des Browsers verschwindet, und wenn dann zurückgescrollt wird, ist das dargestellte Fractal entweder gar nicht mehr oder nicht mehr vollständig vorhanden oder hat nicht mehr ganz die korrekte Form. Wird die Seite "nach hginten" geschoben und eine neue Seite darüber geöffnet, und später weider in den Vordergrund geholt, liegen über dem Anzeigebereich des Applets "Reste" der vorher angezeigten Seite.
Mich verblüfft das etwas. Irgendwo müßte ich wahrscheinlich ein "repaint" oder so etwas in meinen Code einbauen. Ich habe zur Demonstration mal eine Seite mit vier Varianten des Applets hochgeladen nach http://home.arcor.de/schnauss/temp/julia.htm. Mit dem Code ist das ja immer bissel problematisch, deshalb steht der JAVA-Code auch auf dieser Demonstrationsseite.
Wär schön, wenn jemand nen Hinweis hätte, da ich diese dekorativen Möglichkeiten mit fraktalen Grafiken gerne einsetzen möchte.

Grüße aus Berlin

Christoph S.

  1. moin Christoph!

    ich habe an einem kleinen (2KB) Applet herumgebastelt, das ich zu dekorativen Zwecken einsetzen möchte. Es soll nichts anderes tun, als eine fraktale Grafik (Juliamenge) zeichnen  -  das tut es auch.

    mhh, hab letzte woche in der Schule gelernt, wie man mit Java einen Button macht: Dabei hatte unser Lehrer mehr Syntax-Fehler als ich ;-)

    Aber: wenn die Seite, in der es enthalten ist, gescrollt wird und das Appelt damit aus dem Anzeigebereich des Browsers verschwindet, und wenn dann zurückgescrollt wird, ist das dargestellte Fractal entweder gar nicht mehr oder nicht mehr vollständig vorhanden oder hat nicht mehr ganz die korrekte Form. Wird die Seite "nach hginten" geschoben und eine neue Seite darüber geöffnet, und später weider in den Vordergrund geholt, liegen über dem Anzeigebereich des Applets "Reste" der vorher angezeigten Seite.
    Mich verblüfft das etwas. Irgendwo müßte ich wahrscheinlich ein "repaint" oder so etwas in meinen Code einbauen. Ich habe zur Demonstration mal eine Seite mit vier Varianten des Applets hochgeladen nach http://home.arcor.de/schnauss/temp/julia.htm. Mit dem Code ist das ja immer bissel problematisch, deshalb steht der JAVA-Code auch auf dieser Demonstrationsseite.
    Wär schön, wenn jemand nen Hinweis hätte, da ich diese dekorativen Möglichkeiten mit fraktalen Grafiken gerne einsetzen möchte.

    ärgerlich, ne?
    IMHO ist das problem das folgende: sowohl das PlugIn verursacht diesen ärgerlichen effekt, da das 1.4er extrem lahm ist IMO, speziell in Kombination mit dem Mozilla, als auch der Browser selber, weil er Applets afaik z.T. aus dem Arbeitsspeicher "ausblendet", verschwinden sie aus dem sichtbereich. (Das problem dabei ist, dass der speicher, den das applet belegt, wesentlich größer sein dürfte, als die vom plugin irrtümlich vorgesehenen 2Kilobyte) werden sie dann geladen, müssen sie erst wieder in den speicher, sofern das überhaupt möglich ist.
    Bei meinem angesprochenen Zwei-Button-Applet aus der Schule dauert es *stoppuhrhol* bei meinem Mozilla geschlagene 1,45 sek, bis die buttons (und aus mehr besteht das teil nicht!) wieder angezeigt werden.
    In dem Falle: SVG/Flash, wobei du sicher SVG nehmen würdest. Java ist IMO für soetwas im PlugIn (und wegen den Browsern, das sollte man dazu sagen) zu langsam. ich weiß garnicht, ob ein 200MHz-PC das teil überhaupt anzeigen kann...

    ach ja, meine Konfiguration zum Nachvollziehen:
    Athlon 700,
    384 MB RAM,
    GeForce 2 Pro,
    Windoof 98 SE (und Suse 8.0... *reboot*)
    SDK 2 (Java-Version 1.4);
    das 1.4er PlugIn für IE und Mozi...

    Fabian

    1. hi Fabian,

      warst ja fix mit deiner Antwort ;-)

      IMHO ist das problem das folgende: sowohl das PlugIn verursacht diesen ärgerlichen effekt, da das 1.4er extrem lahm ist IMO, speziell in Kombination mit dem Mozilla, als auch der Browser selber, weil er Applets afaik z.T. aus dem Arbeitsspeicher "ausblendet", verschwinden sie aus dem sichtbereich.

      Ganz so einfach ist es nicht. Ich habe selber JAVA 1.4.1 installiert, und das geschilderte Problem taucht nur bei dem Applet auf, das ich zur Demonstration auf die angegebene Seite hochgeladen habe. Bei einem anderen Applet, das genau dasselbe tut, jedoch mit einer anderen Figur (keine Juliamengen, sondern eine Mandelbrodt-Menge, also das "Apfelmännchen"), ca. 20 Codezeilen größer ist und einer etwas anderen mathematischen Konstruktion folgt, passiert mir das nämlich nicht.

      (Das problem dabei ist, dass der speicher, den das applet belegt, wesentlich größer sein dürfte, als die vom plugin irrtümlich vorgesehenen 2Kilobyte)

      die Anmerkung ist richtig. Aber ich kann ja im HTML-Dokument die angezeigte Größe gering halten, so daß auch das keine gravierende Rolle spielen dürfte. Auf meiner Demonstrationsseite habe ich es allerdings deutlich größer stehen, als ich es später mal einsetzen möchte.

      In dem Falle: SVG/Flash, wobei du sicher SVG nehmen würdest

      Würde ich, richtig ;-) Allerdings: um denselben Effekt in SVG zu erhalten, muß ich rund 80 KB mit Zahlenkolonnen vollschreiben. Wenn ich weiß, wie ich das mit weniger Aufwand hinkriege, werde ich das bekanntgeben.

      Java ist IMO für soetwas im PlugIn (und wegen den Browsern, das sollte man dazu sagen) zu langsam. ich weiß garnicht, ob ein 200MHz-PC das teil überhaupt anzeigen kann...

      Können kann das  -  sogar ohne Geschwindigkeitsunterschiede  -  auch mein guter alter 486er mit 16 MB RAM, den ich gerade für solche Testzwecke noch im LAN hängen habe (der kann, weil er keinen math. Coprozessor hat, noch nicht einmal Win98, sondern muß bei Win95 "stehenbleiben" und hat den IE 5.0). Daran liegts nicht.

      Grüße aus Berlin

      Christoph S.

      1. nabend Christoph

        warst ja fix mit deiner Antwort ;-)

        mhh, als ob das ein qulitätsmerkmal wäre ;-)

        Ganz so einfach ist es nicht. Ich habe selber JAVA 1.4.1 installiert, und das geschilderte Problem taucht nur bei dem Applet auf, das ich zur Demonstration auf die angegebene Seite hochgeladen habe. Bei einem anderen Applet, das genau dasselbe tut, jedoch mit einer anderen Figur (keine Juliamengen, sondern eine Mandelbrodt-Menge, also das "Apfelmännchen"), ca. 20 Codezeilen größer ist und einer etwas anderen mathematischen Konstruktion folgt, passiert mir das nämlich nicht.

        mhh, das wäre mir jetzt schonmal ein rätsel.
        kommt das gute Java 1.4 mit der Julia nicht klar?

        (Das problem dabei ist, dass der speicher, den das applet belegt, wesentlich größer sein dürfte, als die vom plugin irrtümlich vorgesehenen 2Kilobyte)
        die Anmerkung ist richtig. Aber ich kann ja im HTML-Dokument die angezeigte Größe gering halten, so daß auch das keine gravierende Rolle spielen dürfte. Auf meiner Demonstrationsseite habe ich es allerdings deutlich größer stehen, als ich es später mal einsetzen möchte.

        IMO ist nicht die anzeigegröße relevant (es sei denn du hast ne 512kb-grafikkarte ;-), sondern die rechnungen die durchgeführt werden müssen. sind die zu groß, so tritt das problem zwangsläufig auf. auch hier wieder der verdacht auf Java/Julia-Mengen Disharmonie...

        In dem Falle: SVG/Flash, wobei du sicher SVG nehmen würdest
        Würde ich, richtig ;-) Allerdings: um denselben Effekt in SVG zu erhalten, muß ich rund 80 KB mit Zahlenkolonnen vollschreiben. Wenn ich weiß, wie ich das mit weniger Aufwand hinkriege, werde ich das bekanntgeben.

        weiß ich wohl. ist ärgerlich, unnötig und übertrieben, aber geht ;-)

        Java ist IMO für soetwas im PlugIn (und wegen den Browsern, das sollte man dazu sagen) zu langsam. ich weiß garnicht, ob ein 200MHz-PC das teil überhaupt anzeigen kann...

        Können kann das  -  sogar ohne Geschwindigkeitsunterschiede  -  auch mein guter alter 486er mit 16 MB RAM, den ich gerade für solche Testzwecke noch im LAN hängen habe (der kann, weil er keinen math. Coprozessor hat, noch nicht einmal Win98, sondern muß bei Win95 "stehenbleiben" und hat den IE 5.0). Daran liegts nicht.

        gut. trotzdem die these, dass Java generell langsam ist. (jetzt nicht draufhauen, das ist bei den meisten PlugIns so, aus verständlichen gründen...) ob das hierbei einen untershcied macht ist zurecht zweifelhaft.

        tja, sieht so aus, als konnte ich dir nicht viel weiterhelfen...
        immerhin bleibt festzuhalten: Java mag Julia nicht ;-)

        Fabian

        [der morgen wieder zwei stunden informatik hat, wo er wohl lernen wird, wie man noch einen button macht *g* (und deshalb jetzt in die Heia geht)]

  2. Hallo Christoph S.

    pain(Graphics g) wird jedesmal aufgerufen, wenn irgend ein Teil des Applets neu geziechnet werden muss.
    Also jedesmal wenn Du scrollst oder das Fenster wieder in den Vordergrund holst.
    Du solltest das berechnen der Fraktale also schon in init() erledigen und in paint nur noch das fertige Bild ausgeben.
    So wie Du das implementierst wird die Berechnung dauernd neu angestoßen.

    Grüße

    Daniel

    1. hi Daniel,

      pain(Graphics g) wird jedesmal aufgerufen, wenn irgend ein Teil des Applets neu geziechnet werden muss. Also jedesmal wenn Du scrollst oder das Fenster wieder in den Vordergrund holst. Du solltest das berechnen der Fraktale also schon in init() erledigen und in paint nur noch das fertige Bild ausgeben.

      danke für den Hinweis. Habs eben mal schnell offline durchprobiert. Scheint aber mit einem einfachen "Verschieben" der entsprechenden Anweisungen nach "init()" nicht zu klappen  -  es gibt keine Kompilierfehler, aber es wird dann gar nix gezeichnet.
      Muß ich mal sehen, ob mir noch was dazu einfällt beim Ausprobieren, immerhin ist das möglicherweise der richtige Weg.

      So wie Du das implementierst wird die Berechnung dauernd neu angestoßen.

      Ja, das war auch mein ursprüngliches Konzept. Was ist daran falsch gedacht?

      Grüße aus Berlin

      Christoph S.

      1. Hallo Christoph

        Erklärt ist ja jetzt schon. Auch wenn bei schnellem Scrollen paint nicht für jeden Pixel aufgerufen wird, wird es auf jeden fall sehr oft aufgerufen.

        Ich habe das Applet mal etwas umgeschrieben:

        import java.awt.Graphics;
        import java.awt.Rectangle;
        import java.awt.Color;
        import java.awt.image.BufferedImage;
        import java.applet.Applet;

        public class julia extends Applet implements Runnable {

        Thread drawThread = null;

        int h, b;
          int tiefe = 16;
          double o = 1.0, u = -1.0, l = -1.75, r = 1.75;
          double c_x = -0.75543, c_y = 0.12301;
          boolean drawing = false;
          byte map[][];
          Graphics g;
          BufferedImage i;

        public void start() {
            i = new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_INT_RGB);
            g = i.getGraphics();
            g.setColor(new Color(0, 0, 160));
            drawThread = new Thread(this);
            drawThread.start();
          }

        public void stop() {
            drawThread = null;
            g = null;
          }

        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(i,0,0,new Color(238, 238, 238),null);
          }

        public void run() {
            Rectangle rect = getBounds();
            drawing = true;
            h = rect.height;
            b = rect.width;
            map = new byte[b][h];
            zeichnen(1.0, 1.0);
            map = null;
            drawing = false;
          }

        void zeichnen(double x, double y) {
            double r, neux, neuy;
            int num;
            int xtmp = tempx(x), ytmp = tempy(y);

        map[xtmp][ytmp]++;
            g.drawLine(xtmp, ytmp, xtmp, ytmp);
            drawThread.yield();

        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);
            }
            repaint(xtmp,ytmp,1,1);
        /* Wenn man das hier raus nimmt, flimmert das bild nicht mehr.
        Allerdings sieht man auch nicht, wie das Fraktal sich aufbaut.
        Wenn man das will, sollte man sich hier etwas optimaleres überlegen. evt. all 100ms neu repaint() o.ä.
        */
          }
        }

        Grüße

        Daniel

        1. 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.

          1. hi ihr beiden, Slyh und Daniel ;-)

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

            "aber das war doch gar nicht nötig in dieser Ausführlichkeit" *g*

            im Ernst: ihr habt mich mit euren "Umarbeitungen" doch etwas überrascht. Ich selber hätte es gar so ausführlich wohl nicht gebraucht (es hätte ein Hinweis auf den herausgefischten möglichen "Schwachpunkt" gereicht), aber im Forum lesen ja immer viele andere Leute mit, und diese "stillen Mitleser" kriegen mit meiner Vorlage und euren postings jetzt drei prima Codebeispiele, die jedes für sich zwar funktionieren  -  aber auch jedes für sich noch ein paar Fragen offenlassen und "Macken" haben. Ich finde das insgesamt prima ...

            Erstmal zu Daniels Vorschlag: wenn man das so nimmt, wie du es gepostet hast, Daniel, ist nach dem Kompilieren zwar mein Ursprungsproblem mit dem "Scroll-Effekt" behoben. Aber: Klicke ich auf "Aktualisieren", ist die Fraktal-Grafik nicht mehr da, ich muß erstmal scrollen, rauf und wieder runter, dann ist sie plötzlich da  -  bloß stimmt mein Hintergrund nicht mehr, der ist jetzt einförmig schwarz.
            (Ich bitte um Entschuldigung, wenn ich das jetzt, auch wegen der Uhrzeit, nicht genauer befragen möchte)

            Zu Slyh:

            ähm, du hättest mir einen klitzekleinen Gefallen tun und hier:

            public class Julia extends Applet implements Runnable {

            auch bei der Kleinschreibung für "julia" bleiben zu können ;-)
            aber egal: wenn ich das so, wie du es gepostet hast, kompiliere, ist (anders als bei Daniels Vorschlag) mein hellgrauer Hintergrund noch vorhanden. Aber der "Scroll-Effekt" ist nur teilweise behoben: bei (ungefähr) jedem dritten "Aktualisieren" der Seite oder eben einem Hoch- und Runterscrollen liegt ein "Zufallsstreifen" über der Grafikanzeige des Applets.

            Ich habe mir beide Vorschläge, für die ich dankbar bin, säuberlich rausgeschnipselt und archiviert. Die "Wahrheit" liegt voraussichtlich irgendwo dazwischen, aber das krieg ich heute nacht nicht mehr endgültig hin.

            Ich bedanke mich ausdrücklich für eure jeweiligen Erläuterungen und will jetzt nur noch auf eins eingehen:

            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.

            Das trifft es sehr exakt.  Allerdings: "Fertige Lösungen"  -  oder besser: Lösungsvorschläge  -  wie ihr sie unerwarteterweise geliefert habt, sind eine höchst erfreuliche Zugabe. Wenn ich mir auch von euch bzw. vom Forum insgesamt meine "Denkarbeit" keineswegs abnehmen lassen will, wäre ich aber ganz schön doof, wenn ich eine "fertige Lösung" ignrieren wollte ;-) Mir gehts tatsächlich im Grundsatz um die "Energie des Verstehens", und dabei kann ja bisweilen auch ein vollständiges Script helfen. Wenn ich selber auf andere postings einzugehen versuche, verhalte ich mich schließlich auch nicht anders.
            Ich lese eure Lösungen _nicht_ so, daß ich damit etwas erhalten hätte, was jetzt gegenüber meiner Bastelei endlich "fix und fertig" ist, sondern ich lese sie so: da hat jemand meine Fragestellung aufgegriffen und bietet mir _seine_ Sichtweise an und hilft mir damit, den für mich richtigen Lösungsweg zu finden und zu verstehen. Ich kann jetzt besser und mit erweitertem Hintergrundwissen weiterarbeiten.

            'tschuldigung für diesen kurzen Ausflug in die Ideenwelt der Motivationen.

            Grüße aus Berlin

            Christoph S.

            1. Hallo Christoph

              1. Das Reload problem:
              Der Browser startet das Applet in diesem Fall komplett neu.
              Bei Mozilla wird es dann auch brav neu gezeichnet.

              2. Das Backgroundproblem
              Das liegt daran, dass ich bei BufferedImage einen Imagetyp angegeben habe, der keine Transparenz unterstüzt.
              Wenn man z.B. TYPE_4BYTE_ABGR angibt, stimmt auch der Hintergrund.

              3. Das Flimmerproblem
              Sylts Lösung funktioniert da. update überschreiben und fertig.

              Grüße

              Daniel

            2. Hallo,

              ähm, du hättest mir einen klitzekleinen Gefallen tun und hier:

              public class Julia extends Applet implements Runnable {
              auch bei der Kleinschreibung für "julia" bleiben zu können ;-)

              Sorry. :-)
              Mich hat das kleingeschriebene Julia einfach irgendwie gestört. Außerdem
              beschwert sich mein VisualAge wenn ich ihm kleingeschrieben Klassenname
              präsentiere.
              Auf die Java Code Conventions habe ich schon weiter oben hingewiesen.
              Hier gibt's den Link noch einmal in anklickbarer Form:
              http://java.sun.com/docs/codeconv/
              Aber ich hätte wirklich auf die Änderung hinweisen sollen. Tut mir leid.

              aber egal: wenn ich das so, wie du es gepostet hast, kompiliere, ist (anders als bei Daniels Vorschlag) mein hellgrauer Hintergrund noch vorhanden.

              Das kommt daher, daß das Bild nach dem Erstellen zuerst mit der hellgrauen
              Farbe gefüllt wird. (siehe fillRect)

              Aber der "Scroll-Effekt" ist nur teilweise behoben: bei (ungefähr) jedem dritten "Aktualisieren" der Seite oder eben einem Hoch- und Runterscrollen liegt ein "Zufallsstreifen" über der Grafikanzeige des Applets.

              Das kann ich bei mir (Mozilla + JDK1.4.01) wiederum nicht nachvollziehen.
              Vielleicht liegt es an deiner Konfiguration oder an einem Bug in deiner
              JDK. Komisch ist das jedenfalls.

              Gruß
              Slyh

    2. Hallo Daniel und vor allem Christoph S.

      pain(Graphics g) wird jedesmal aufgerufen, wenn irgend ein Teil des Applets neu geziechnet werden muss.
      Also jedesmal wenn Du scrollst oder das Fenster wieder in den Vordergrund holst.

      Theoretisch wird also alleine durch das Scrollen von 5 Pixeln die paint()-
      Methode 5-mal aufgerufen, 5-mal das Graphics-Objekt kopiert (wieso eigentlich?)
      und 5-mal ein neuer Thread erzeugt und gestartet. Alle diese Threads versuchen
      nun gleichzeitig und parallel das Fraktal zu berechnen und darzustellen.
      Bei meinem Scrollversuch waren es letztendlich über 100 Threads, die gleich-
      zeitig am werkeln waren. Dabei kam es dann zu zahlreichen NullPointerExceptions,
      weil in der run()-Methode irgendwie "map" auf null gesetzt wird usw.

      Du solltest das berechnen der Fraktale also schon in init() erledigen und in paint nur noch das fertige Bild ausgeben.

      Naja, er kann auch in init() bzw. besser in start() einen Thread anstoßen,
      der das Fraktal berechnet und zeichnet. Allerdings sollte nicht direkt in
      die Zeichenfläche des Applets gezeichnet werden, sondern besser in ein Image.
      Dieses Image wird dann in paint() immer über auf die Applet-Zeichenfläche
      gemalt. Direktes Zeichnen in die Applet-Zeichenfläche ist flüchtig. Daher
      ja auch die paint()-Methode.

      So wie Du das implementierst wird die Berechnung dauernd neu angestoßen.

      So wie es momentan implementiert ist, wird das Applet auch nur durch den
      Aufruf der Methode paint() überhaupt angestoßen. Genau das was jetzt in
      paint() steht, sollte aber eigentlich in start() stehen. Diese Methode wird
      nämlich beim Start des Applets aufgerufen. Paint wird - wie du ja schon gesagt
      hast - bei jedem Neuzeichnen aufgerufen. Das Applet "funktioniert" auch nur
      deshalb, weil beim ersten Anzeigen des Applets eben paint() aufgerufen wird.
      Korrekt müßten alle Operationen, die zum (evtl. auch erneuten) Starten des
      Applets notwendig sind, in start() stehen.

      Gruß
      Slyh

      1. hi,

        Theoretisch wird also alleine durch das Scrollen von 5 Pixeln die paint()- Methode 5-mal aufgerufen, 5-mal das Graphics-Objekt kopiert (wieso eigentlich?) und 5-mal ein neuer Thread erzeugt und gestartet. Alle diese Threads versuchen nun gleichzeitig und parallel das Fraktal zu berechnen und darzustellen.

        ups. stimmt. Hab ich nicht gesehen, weil:

        Bei meinem Scrollversuch waren es letztendlich über 100 Threads, die gleichzeitig am werkeln waren. Dabei kam es dann zu zahlreichen NullPointerExceptions

        NullPointerExceptions hab ich auf der Konsole nicht angezeigt bekommen (JAVA 1.4.1 beta). Warum eigentlich nicht? Dann hätt ich ne Orientierung gehabt ... Hab das Ding übrigens unter Benutzung einiger "Vorlagen", die ich mir im Lauf der Zeit irgendwo zusammengesucht hatte, auf ner Windows-Kiste zusammengeschraubt. Ist die Konsole unter FreeBSD aussagefähiger (hab ich noch gar nicht probiert)?

        Naja, er kann auch in init() bzw. besser in start() einen Thread anstoßen, der das Fraktal berechnet und zeichnet

        hm, das Ganze in "start()" einzubauen, ist vielleicht der effektivste Weg.

        Allerdings sollte nicht direkt in die Zeichenfläche des Applets gezeichnet werden, sondern besser in ein Image. Dieses Image wird dann in paint() immer über auf die Applet-Zeichenfläche gemalt. Direktes Zeichnen in die Applet-Zeichenfläche ist flüchtig. Daher ja auch die paint()-Methode.

        richtig, aber das ist meines Erachtens das kleinste Problem dabei und läßt sich am schnellsten lösen.

        Genau das was jetzt in paint() steht, sollte aber eigentlich in start() stehen

        ok, und dankesehr, ich habs gelesen und werde es beherzigen. Wenns nicht klappt, melde ich mich wieder ;-)

        Der Sinn des Ganzen liegt für mich ganz schlicht und einfach darin, daß ich die grafischen Ergebnisse dieser im Grunde genommen sehr simplen mathematischen Konstruktionen außerordentlich schätze. Ich finde Fraktale nach wie vor äußerst dekorativ.

        Grüße aus Berlin

        Christoph S.

  3. hi Forum ;-)

    der Thread hat mir bisher sehr viel gebracht. Aber ich habe mit einem zweiten Applet ebenfalls Schwierigkeiten und möchte euch gerne bitten, auch da mal draufzuschauen. Die temporäre Adresse ist:
    http://home.arcor.de/schnauss/temp/mandel.htm

    Auch hier wird eine Fraktal-Grafik gezeichnet, allerdings gibt es hier das Problem nicht, daß die Grafik-Ausgabe beim Scrollen verschwindet oder zerhackt wird. Dafür ist es rätselhaft und absolut zufallsbedingt, ob das Applet überhaupt "arbeiten" und etwas anzeigen möchte. Unter Umständen muß man mehrfach "aktualisieren", bis die Grafik-Ausgabe des Applets überhaupt angezeigt wird, und das ist hier das Problem. Natürlich möchte ich, daß ein Applet auch brav seine Arbeit verrichtet, sobald die Seite, in der es enthalten ist, aufgerufen wird.

    Wenn ihr mögt, schaut mal drauf. Jede Sachdiskussion ist mir sehr willkommen.

    Grüße aus Berlin

    Christoph S.

    1. Hallo Christoph,

      Dafür ist es rätselhaft und absolut zufallsbedingt, ob das Applet überhaupt "arbeiten" und etwas anzeigen möchte. Unter Umständen muß man mehrfach "aktualisieren", bis die Grafik-Ausgabe des Applets überhaupt angezeigt wird, und das ist hier das Problem. Natürlich möchte ich, daß ein Applet auch brav seine Arbeit verrichtet, sobald die Seite, in der es enthalten ist, aufgerufen wird.

      Ich kann dein Problem nicht reproduzieren. Getestet habe ich mit Netscape
      Navigator 4.79 und JDK 1.3.1 sowie mit Mozilla 1.1b und JDK 1.4.01. Beide
      Applets werden sofort korrekt angezeigt.

      Es sind mir jedoch einige Dinge an deinem Code aufgefallen, die sicherlich
      noch verbessert werden können:

      • Auf der Konsole wird beim ersten Anzeigen des Applets eine NullPointerException
        angezeigt. Das kommt daher, daß du "img" erst in der Methode "update()" einen
        Wert zuweist. Beim ersten Anzeigen des Applets wird aber (allem Anschein
        nach) nur die "paint()"-Methode aufgerufen. Erst durch den repaint()-Aufruf
        in "run()" wird "img" gesetzt.
      • Du startest den Thread schon in der init()-Methode. Sowas sollte eigentlich
        in "start()" erfolgen. In init() sollte das Applet initialisiert werden, also
        z.B. Objekte erzeugt oder Vorberechnungen durchgeführt werden. Start() wird
        evtl. sehr viel später ausgeführt, nämlich erst dann, wenn das Applet auch
        wirklich loslaufen soll.
      • Du schreibst Klassennamen klein, dafür aber manche Instanzvariablen groß.
        In diesem Fall erzeugst du dir z.B. ein Objekt der Klasse "Thread" und nennst
        dieses Objekt auch "Thread". Mich wundert es, daß der Compiler soetwas
        überhaupt mitmacht. :-) Ein menschlicher Leser wird damit noch viel weniger
        Freude haben. Ich empfehle dir die Lektüre der Code Conventions for the Java
        Programming Language (http://java.sun.com/docs/codeconv/). Dort sind einfache
        Regeln zur Code-Gestaltung festgehalten, die das Lesen des Codes sehr
        erleichtern. Die meisten Java-Programmierer (die ich kenne) halten sich mehr
        oder weniger vollständig an diese Regeln. Das solltest du auch. Du wirst es
        dir beim späteren Lesen des Codes selbst danken.

      Gruß
      Slyh

      1. hallo Slyh,

        Ich kann dein Problem nicht reproduzieren. Getestet habe ich mit Netscape Navigator 4.79 und JDK 1.3.1 sowie mit Mozilla 1.1b und JDK 1.4.01. Beide Applets werden sofort korrekt angezeigt.

        Komisch. Mit Netscape 4.7x habe ich es selbst nicht probiert, weil der auf meiner (Windows)Kiste eh dasselbe Plugin wie Netscape 7.0 benutzt, also für _diese_ Fragetsellung nix Neues bringt. Auf meiner SUSE hab ich ihn gar nicht mehr. Aber der Konqueror 3 (in FreeBSD 4.7) hat bei mir dieselben Probleme wie der IE gehabt, die ich kurz benannt hatte.

        Es sind mir jedoch einige Dinge an deinem Code aufgefallen, die sicherlich noch verbessert werden können

        ich muß, falls das noch nicht deutlich geworden ist, zum Code noch was sagen. Ich habe das mal vor ungefähr drei Jahren aus mehreren verschiedenen "Vorlagen", die ich irgendwo aus dem Internet gefischt hatte, zusammengeschustert und war damals einfach bloß froh, daß es "funktionierte". Jugendsünden ... Im Moment bin ich dabei, meine "alten" Applet-Codes zu überarbeiten. Drei Jahre waren auch genügend Zeit, etwas mehr Verständnis für JAVA zu erwerben.

        • Auf der Konsole wird beim ersten Anzeigen des Applets eine NullPointerException angezeigt. Das kommt daher, daß du "img" erst in der Methode "update()" einen Wert zuweist

        [ ... ]
        alles richtig. Habs mir rausgezogen und archiviert. Allerdings habe ich immer noch das Problem, daß ich auf der Konsole keine NullPointerException angezeigt bekomme.

        • Du schreibst Klassennamen klein, dafür aber manche Instanzvariablen groß.

        das wußte ich "damals", als ich diesen Code zusammengeschraubt habe, nicht besser. Heute allerdings weiß ich es besser, was auch einer der Gründe ist, weshalb ich an "meine" Applets zur Zeit rangegangen bin und sie modernisieren möchte, ohne den gewünschten "Effekt", nämlich die Anzeige der fraktalen Grafik, zu verlieren.

        [ ... ] Die meisten Java-Programmierer (die ich kenne) halten sich mehr oder weniger vollständig an diese Regeln. Das solltest du auch

        Ich bin fest entschlossen dazu und für entsprechende Hinweise dankbar. Als "Java-Programmierer" sehe ich mich übrigens nicht, ich bin allerdings stark daran interessiert, auch mit JAVA möglichst wenig Fehler zu machen.

        danke dir für deine Geduld.

        Christoph S.