verschiedene Zeichenebenen

hallo, und im vorraus schon einmal danke für eure zeit!

ich möchte einige geometrische formen unterschiedlicher farbe zeichnen, die sie gegenseitig überlappen (für die dies interessiert, es handelt sich um ein fraktal, den pythagoras-baum Pythagoras-Baum ? Wikipedia).
das problem an der ganzen sache ist, dass es unmöglich ist, die teile die als oberstes zu sehen sein sollen auch zeitlich zuletzt zu zeichnen. so dachte ich mir erschaffe ich einfach mehrere ebenen und zeichne dann einfach in die passende ebene. dies funktioniert auch mit jpanels die übereinander liegen und durchsichtig sind. ich wollte für jedes jpanel ein anderes graphics objekt benutzen auf das dann gezeichnet werden kann. doch nun weiß ich nicht ob man überhaupt mehrere graphics objekte gleichzeitig haben kann, da diese ja nicht instanziiert werden dürfen und wie man diese graphics objekte "in" das jpanel bekommt. hier ist der code:

Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.JPanel;

public class Pythagoras_Tree extends Frame{

  static final int WIDTH = 1024-8;
  static final int HEIGHT = 768-34;
  static final int MAX_ITERATION = 16;
  static JPanel[] draw = new JPanel[MAX_ITERATION+1];
  static Graphics2D[] g2d = new Graphics2D[MAX_ITERATION+1];
  static final float TRUNK_RED = 139f/255f;
  static final float TRUNK_GREEN = 90f/255f;
  static final float TRUNK_BLUE = 43f/255f;
  static final float CROWN_RED = 0f;
  static final float CROWN_GREEN = 155f/255f;
  static final float CROWN_BLUE = 0f;


  Pythagoras_Tree(){
    addWindowListener(new MyFinishWindow());
    createAndAddComponents();
    pyth(0, 423,730, 591,730, 0);
  }

  public class MyFinishWindow extends WindowAdapter
  {
    public void windowClosing(WindowEvent e)
    {
      System.exit(0);
    }
  }

  public void createAndAddComponents(){
    /*int z = 0;
    while (z<=MAX_ITERATION){
      Graphics2D g2d[z]; = Graphics2D;
      z++;
    }*/
    FlowLayout flow0 = new FlowLayout();
    flow0.setHgap(0);
    flow0.setVgap(0);
    
    draw[0] = new JPanel();
    draw[0].paint(g2d[0]);
    draw[0].setLayout(flow0);

    int i = 1;
    while (i<MAX_ITERATION){
      draw[i] = new JPanel();
      draw[i].paint(Graphics g){
        g2d[i] = (Graphics2D)g;
      }
      draw[i].paint(g2d[i]);
      draw[i].setOpaque(false);
      draw[i].setLayout(flow0);
      draw[i-1].add(draw[i]);
      i++;
    }
  }
  
  public static void pyth (double alpha, double ax, double ay, double bx, double by, int iteration){
    if(iteration<=MAX_ITERATION){
      double length = Math.sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay));

      double nax,nay,nbx,nby,cx,cy;
      nax = ax+Math.sin(alpha)*length;
      nay = ay-Math.cos(alpha)*length;
      nbx = bx+Math.sin(alpha)*length;
      nby = by-Math.cos(alpha)*length;
      cx = nax+Math.cos(alpha-Math.PI/4.0)*(length/Math.sqrt(2));
      cy = nay+Math.sin(alpha-Math.PI/4.0)*(length/Math.sqrt(2));

      float red = ((MAX_ITERATION-iteration)*TRUNK_RED+iteration*CROWN_RED)/MAX_ITERATION;
      float green = ((MAX_ITERATION-iteration)*TRUNK_GREEN+iteration*CROWN_GREEN)/MAX_ITERATION;
      float blue = ((MAX_ITERATION-iteration)*TRUNK_BLUE+iteration*CROWN_BLUE)/MAX_ITERATION;

      g2d[iteration].setColor(new Color(red,green,blue));
      g2d[iteration].drawLine((int)ax,(int)ay, (int)nax,(int)nay);
      g2d[iteration].drawLine((int)bx,(int)by, (int)nbx,(int)nby);
      g2d[iteration].fillPolygon(new int[]{(int)ax,(int)nax,(int)cx,(int)nbx,(int)bx}, new int[]{(int)ay,(int)nay,(int)cy,(int)nby,(int)by}, 5);

      pyth(alpha-Math.PI/4, nax,nay, cx,cy, iteration+1);
      pyth(alpha+Math.PI/4, cx,cy, nbx,nby, iteration+1);
    }
  }

  public static void main (String[] args){
    Pythagoras_Tree main = new Pythagoras_Tree();
    main.setVisible(true);
    main.setSize(WIDTH+8,HEIGHT+34);
    main.setResizable(false);
    main.validate();
  }

}

jetzt mekelt der compiler bei
Java:
draw[i].paint(Graphics g){
        g2d[i] = (Graphics2D)g;
      }
rum.
versuche ich in der pyth methode nicht g2d[iteration] sondern draw[iteration].getGraphics() zu verwenden, erhalte ich eine null pointer exception.
ich habe schon alles versucht und gegoogled aber ich finde einfach keine lösung. hat jemand von euch vielleicht eine idee? danke :)
 

Marco13

Top Contributor
Graphics-Objekte so "zwischenzuspeichern" ist ... flasch. (Und das muss "flasch" heißen, anderenfalls wäre es ja richtig :D ).

Alles, was gezeichnet wird, muss von der paint- bzw. paintComponent-Methode aus gezeichnet werden - und zwar in das Graphics-Objekt, das dort übergeben wird.

Eine Möglichkeit wäre (ganz grob) die Linien und Polygone, die du da Berechnest, z.B. in ArrayLists zu speichern, und diese Listen dann in der paint-Methode durchzugehen und die einzelnen Elemente zu zeichnen....
 
sowas habe ich auch schon überlegt, aber in der letzten iteration gibt es 2^16 elemente und insgesamt 2^17-1. kann man so viele überhaupt zwischenspeichern und selbst wenn würde das dann nich ewig zur berechnung dauern?
 
S

SlaterB

Gast
> das problem an der ganzen sache ist, dass es unmöglich ist, die teile die als oberstes zu sehen sein sollen auch zeitlich zuletzt zu zeichnen.

wieso?

bei nur 1 Mio. Bildpunkten lohnt sich übrigens auch kaum wer weiß wie viele Milliarden minimale Linien zu berechnen

--------

ansonsten bietet sich an auf durchsichtigen Bildern zu malen, diese Bilder haben jeweils ein Graphics-Objekt, welches du auch zu beliebigen Zeitpunkt bemalen kannst,
am Ende die Bilder übereinander,

übe das aber mit 3-4 Testlinien, nicht unbedingt mit der komplizierten Rekursion..
 
> das problem an der ganzen sache ist, dass es unmöglich ist, die teile die als oberstes zu sehen sein sollen auch zeitlich zuletzt zu zeichnen.

wieso?

das liegt daran wie die rekursion aufgebaut ist. es wird ja immer ein ast bis zum ende geführt und dann kommt der nächste. würde man die teile in der reihenfolge der iteration malen wollen, müsste man bei der letzten 2^17*4 eckpunkte zwischenspeichern.

> bei nur 1 Mio. Bildpunkten lohnt sich übrigens auch kaum wer weiß wie viele Milliarden minimale Linien zu berechnen

das sind garnich so viele wie man bei 2^17 denkt. ausgerechnet sind das 131071 formen.

> ansonsten bietet sich an auf durchsichtigen Bildern zu malen, diese Bilder haben jeweils ein Graphics-Objekt, welches du auch zu beliebigen Zeitpunkt bemalen kannst,
am Ende die Bilder übereinander,

klingt interessant. meinst du BufferedImages? wie kann man denn auf deren graphics objekte zugreifen?

mir ist grad ne mögliche lösung eingefallen, die is aber ziemlich rechenintensiv und auch nich wirklich sauber. das ding einfach so oft wie es iterationen gibt berechnen und jeweils aber immer nur eine iteration zeichnen und dabei immer weiter aufsteigen. dauert aber wirklich lange dann. ich würde gerne noch ne lösung finden wie ichs mir eigentlich gedacht hatte, zumal ich glaube, dass ich das später noch bei anderen sachen brauchen werde. es muss doch ne möglichkeit geben automatisch auf ein panel zu zeichnen?!
 

Marco13

Top Contributor
Falls du das mit den BufferedImages machen willst:
Java:
// Erstellen
BufferedImage layers[] = new BufferedImage[n]
for (int i=0; i<n; i++)
{
    layers[i] = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
}

// Reinmalen
Graphics g = layers[0].createGraphics();
g.drawSomething();
g.dispose();


// Alle Bilder in der paintComponent malen:
for (int i=0; i<n; i++)
{
    g.drawImage(layers[i], 0, 0, this);
}
 
S

SlaterB

Gast
@DocTylerDurden
ok, 2^17 vs 10^17, dann ist aber auch das Speichern nicht so aufwendig

der Trick beim Zeichnen wäre ansonsten auch Auslassen,
nicht alles muss immer berechnet werden und auch nicht jede Berechnung muss direkt gemalt werden,

lasse die Rekursion mehrmals bei 0 anfangen,
berechne erste bis Tiefe 1, male alles,
berechne dann bis Tiefe 2, male nur die Tiefe 2, Tiefe 1 auslassen
usw.

edit: ok, hast du dann auch geschrieben ;)

> dauert aber wirklich lange dann.

den höchsten Iterationsschritt, der doch bestimmt 50% der Arbeit ausmacht, musst du nur einmal berechnen,
insgesamt kann die Zeit nicht mehr als um ~50% ansteigen und das sollte kein Problem sein,
ansonsten wäre die einmalige Berechnung ja auch schon langsam, dann ist es auch kaum schlimmer geworden
 
Zuletzt bearbeitet von einem Moderator:
yo auf jeden. wenn man davon ausgeht, dass die berechnung aller polygone gleich lang dauert sinds 50%, weil ja gilt: 2^0 + 2^1 + 2^2 + ... + 2^n = 2^(n+1)-1. also sinds gesamt 2*2^n (-1) schritte und die letzte iteration hat 2^n, also die hälfte. nun kommt die vorletzte iteration 2x, die vorvorletzte 3x usw. also ergibt sich für die neue zeit: 0.5 + 0.25*2 + 0.125*3 + 1/8*4 + 1/16*5 + ... die folge geht gegen 2 hab ich grad ausgerechnet. also dauerts doppelt so lange, geht ja voll klar.

nun ist aber tatsächlich schon der punkt gekommen, wo es so nicht weitergeht. ich will nämlich nen random faktor bei den astlängen und den winkeln einbaun. und diese randomkeit kann man ja nicht mehrmals erzielen, dann wärs ja nich mehr random. die äste würden iwo inner luft schweben statt am stamm. also muss es jetz unausweichlich so sein, dass ich das auf unterschiedliche ebenen zeichne.

wie kann ich denn nun von außen auf ein jpanel zeichnen? ???:L ;(


edit: ich hatte die antwort von marco13 überlesen, so geht ja auch, ziemlich genial sogar. aber falls jemand ne idee hat wie mans mit den panels machen kann würde ich mich doch sehr freuen. das nervt sonst auch immer, dass man nur in der paint methode zeichnen kann.
 
Zuletzt bearbeitet:
S

SlaterB

Gast
mit JPanel und paint kannst du nicht weit kommen,

zum Zufall nochmal:
ein Random-Objekt kann man mit einem Anfangswert versehen (seed), dann ist die Reihenfolge der Zufallszahlen immer gleich,
damit nicht jeder Programmablauf gleich aussieht (was zum testen durchaus interessant ist) kann man den seed einmal zufällig wählen und dann mehrfach verwenden,

diese Richtung wäre also mit Random nicht völlig verbaut
 
so, also ich habs jetz geschafft so wie ichs mir vorgestellt hatte. der trick is, dass man die panels erst einmal leer zeichnen muss, damit graphics objekte für sie geschaffen werden und auf diese dann erst mit .getGraphics() zeichnen kann. falls es jemanden interessiert, das sieht dann so aus:

Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.JPanel;

public class Pythagoras_Tree{

  public static Frame main;
  static final int WIDTH = 1024-8;
  static final int HEIGHT = 768-34;
  static final int MAX_ITERATION = 12;
  static JPanel[] draw = new JPanel[MAX_ITERATION+1];
  static final float TRUNK_RED = 139f/255f;
  static final float TRUNK_GREEN = 90f/255f;
  static final float TRUNK_BLUE = 43f/255f;
  static final float CROWN_RED = 0f;
  static final float CROWN_GREEN = 155f/255f;
  static final float CROWN_BLUE = 0f;
    
    
  Pythagoras_Tree(){
    main = new Frame("Pythagoras Tree");
    main.addWindowListener(new MyFinishWindow());
    createAndAddComponents();
  }

  public class MyFinishWindow extends WindowAdapter
  {
    public void windowClosing(WindowEvent e)
    {
      System.exit(0);
    }
  }

  public void createAndAddComponents(){

    FlowLayout flow0 = new FlowLayout();
    flow0.setHgap(0);
    flow0.setVgap(0);
    
    draw[0] = new JPanel();
    draw[0].setLayout(flow0);
    main.add(draw[0]);

    int i = 1;
    while (i<=MAX_ITERATION){
      draw[i] = new JPanel();
      draw[i-1].add(draw[i]);
      draw[i].setPreferredSize(new Dimension(WIDTH,HEIGHT));
      draw[i].setOpaque(false);
      draw[i].setLayout(flow0);
      i++;
    }
  }
  
  public static void pyth (double alpha, double ax, double ay, double bx, double by, int iteration){
    if(iteration<=MAX_ITERATION){
      double length = Math.sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay));

      double nax,nay,nbx,nby,cx,cy;
      nax = ax+Math.sin(alpha)*length;
      nay = ay-Math.cos(alpha)*length;
      nbx = bx+Math.sin(alpha)*length;
      nby = by-Math.cos(alpha)*length;
      cx = nax+Math.cos(alpha-Math.PI/4.0)*(length/Math.sqrt(2));
      cy = nay+Math.sin(alpha-Math.PI/4.0)*(length/Math.sqrt(2));

      float red = ((MAX_ITERATION-iteration)*TRUNK_RED+iteration*CROWN_RED)/MAX_ITERATION;
      float green = ((MAX_ITERATION-iteration)*TRUNK_GREEN+iteration*CROWN_GREEN)/MAX_ITERATION;
      float blue = ((MAX_ITERATION-iteration)*TRUNK_BLUE+iteration*CROWN_BLUE)/MAX_ITERATION;

      Graphics graph = draw[iteration].getGraphics();
      //System.out.println(iteration+"   "+draw[iteration]);
      //System.out.println(iteration+"   "+graph);
      graph.setColor(new Color(red,green,blue));
      graph.fillPolygon(new int[]{(int)ax,(int)nax,(int)cx,(int)nbx,(int)bx}, new int[]{(int)ay,(int)nay,(int)cy,(int)nby,(int)by}, 5);
      graph.drawPolygon(new int[]{(int)ax,(int)nax,(int)cx,(int)nbx,(int)bx}, new int[]{(int)ay,(int)nay,(int)cy,(int)nby,(int)by}, 5);
      pyth(alpha-Math.PI/4, nax,nay, cx,cy, iteration+1);
      pyth(alpha+Math.PI/4, cx,cy, nbx,nby, iteration+1);
    }
  }

  public static void main (String[] args){
    new Pythagoras_Tree();
    main.setVisible(true);
    main.setSize(WIDTH+8,HEIGHT+34);
    main.setResizable(false);
    main.validate();
    pyth(0, 423,730, 591,730, 0);
  }

}

ändert aber auch nix. :lol: wenn in einem tiefer liegenden panel gezeichnet wird überdeckt das trotzdem das darüberliegende. dann mach ich das weiterhin mit den BufferdImages, das problem dabei is bloß, dass man immer erst warten muss bis alles fertig errechnet ist und es dann als ganzes erst gezeigt wird und man so den aufbau nich mitverfolgen kann. aber is ja auch nich so schlimm.
zummindest hab ich jetz gelernt wie man außerhalb der paint methode zeichen kann :toll:
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
G listener repaint() - verschiedene Darstellung AWT, Swing, JavaFX & SWT 24
E verschiedene Cursor setzen AWT, Swing, JavaFX & SWT 1
I GUI, das verschiedene Panels hat (Von Seite zu Seite navigieren) AWT, Swing, JavaFX & SWT 7
RedEagle JavaFX Verschiedene Bereiche miteinander verknüpfen AWT, Swing, JavaFX & SWT 7
H 3 verschiedene Nachrichten in einer FXML View die Infos kommen aus DB AWT, Swing, JavaFX & SWT 4
E wie fängt man verschiedene Ereignisse ein mit MVC ? AWT, Swing, JavaFX & SWT 42
S JavaFX Optimierung für verschiedene Auflösungen AWT, Swing, JavaFX & SWT 12
Bartertown JTable - Verschiedene Komponenten in einer Spalte unterbringen AWT, Swing, JavaFX & SWT 3
H Verschiedene JPanels aus eigenen Klassen in JFrame einfügen, nur ein Panel sichtbar AWT, Swing, JavaFX & SWT 4
V Swing Nimbus Look And Feel verschiedene Buttons AWT, Swing, JavaFX & SWT 8
W Verschiedene Foreground color in Combo SWT Auswahlliste AWT, Swing, JavaFX & SWT 5
L AWT Window, Dialog und verschiedene Betriebssysteme AWT, Swing, JavaFX & SWT 2
M 3D-Grafik verschiedene Texturen auf einen Würfel mappen AWT, Swing, JavaFX & SWT 15
T Swing verschiedene Auflösungen AWT, Swing, JavaFX & SWT 7
J 3D-Grafik JOGL - Verschiedene Perspektiven darstellen AWT, Swing, JavaFX & SWT 5
R JTree - verschiedene Verzeichnisse AWT, Swing, JavaFX & SWT 3
T AWT verschiedene Oberflächen programmieren AWT, Swing, JavaFX & SWT 5
M Verschiedene Layouts anzeigen AWT, Swing, JavaFX & SWT 5
Dit_ Verschiedene Icons in einer JTable-Zelle AWT, Swing, JavaFX & SWT 2
H Swing TableCellRenderer für verschiedene Spalten AWT, Swing, JavaFX & SWT 11
N Verschiedene FormLayout in einem Panelbuilder AWT, Swing, JavaFX & SWT 3
D Verschiedene ActionEvents für ein JButton-Array AWT, Swing, JavaFX & SWT 2
M Swing Swing, MVC über verschiedene Panel AWT, Swing, JavaFX & SWT 4
P verschiedene JPanels einblenden je nach auswahl AWT, Swing, JavaFX & SWT 2
L Focus für KeyListener auf verschiedene Panels AWT, Swing, JavaFX & SWT 2
K Verschiedene ComboBoxen in JTable AWT, Swing, JavaFX & SWT 9
D 2 verschiedene Frames mit einem Button schliessen AWT, Swing, JavaFX & SWT 2
D Mit der Maus in verschiedene Modi wechseln AWT, Swing, JavaFX & SWT 15
I JTable: "GLEICHZEITIG" zwei verschiedene TableMode AWT, Swing, JavaFX & SWT 2
F GridLayout: verschiedene Spaltenbreiten AWT, Swing, JavaFX & SWT 2
S verschiedene Menuleisten AWT, Swing, JavaFX & SWT 2
S In einem button Panel 2 verschiedene TiteledBoarder erzeugen AWT, Swing, JavaFX & SWT 5
T verschiedene Farben in einem Text/Editfeld AWT, Swing, JavaFX & SWT 11
R Fenster in verschiedene Bereiche teilen - aber wie? AWT, Swing, JavaFX & SWT 4
D Mehrere verschiedene Textfelder auslesen? AWT, Swing, JavaFX & SWT 10
Icewind Verschiedene Farben in einer JTextArea AWT, Swing, JavaFX & SWT 3
F Verschiedene Vordergrundfarben in einer TextArea AWT, Swing, JavaFX & SWT 4
G JFileChooser in verschiedene Sprachen? AWT, Swing, JavaFX & SWT 6

Ähnliche Java Themen

Neue Themen


Oben