Probelme mit großen BufferedImage in paintComponent

Status
Nicht offen für weitere Antworten.

Alu

Mitglied
Grüße!
In meiner Swing-Applikation zeichne ich erst in ein BufferedImage, dieses dann in ein JPanel.

Sofern sich die Größe des JPanels nicht ändert, wird bei jedem update ( bzw. ich rufe bei Bedarf repaint() auf ) das BufferedImage gezeichnet. (Damit spare ich Zeit, da ich ne Menge Linien zeichne, nur bei einem resize wird das BufferedImage neu gefüllt )

Funktioniert alles wie es soll, aber: ab einer bestimmten Größe bzw. wenn das BufferedImage sehr groß wird, ist die Darstellung nich mehr korrekt!! Ich bekomme keine OutOfMemoryException bzw. irgendeine andere Exception!

Gibt es da irgendwelche Beschränkungen bei BufferedImage? Vielleicht sollte ich noch darauf hinweisen, dass mein JPanel einem Scrollpane zugeordnet wurde ( jScrollPane.setViewPort( myPanel ) )

Hier ein Codeausschnitt:

Code:
public void paintComponent(Graphics g)
{
    ...

    Graphics2D g2 = (Graphics2D) g;
    Dimension d = this.getSize();
    Graphics2D g2image = g2; 

    ...

     if ( m_graphImage == null || !(d.equals( m_imageDimension )) )
    {
      m_imageDimension = new Dimension();
      m_imageDimension.setSize(d);

      Image myImage = this.createImage( d.width, d.height );

      if ( myImage instanceof BufferedImage )
      {
        m_graphImage = (BufferedImage)myImage;
        g2image = m_graphImage.createGraphics();
      }
   
     g2image.draw( new Line2D.Double( x_old, y_old, x_new, y_new) );  

    ....
    
    g2.drawImage(m_graphImage, null,0,0);
    
    ...
    
}
 
Also ich skaliere meine Grafik indem ich einen Slider verwende.
Da passiert noch nichts bzw. im Viewport wird alles korrekt angezeigt bzw. wie gewünscht.
Wenn ich dann scrolle, ist die Grafik auf einmal leer oder es werden kurze Bereiche der Grafik angezeigt ... witzigerweise erst ab einer bestimmten Größe (ich werd morgen nochmal genau untersuchen, ab wann das genau ist)
Wenn ich den Slider wieder zurück bewege, wird dann ab einer bestimmten Größe auch alles wieder korrekt angezeigt! Wenn ich das BuffereImage rausnehme tritt da Problem überhaupt nicht auf!! Nur das Zeichnen dauert dann sehr lange, was ich nicht will.

Murray hat gesagt.:
Wie äußert sich das Problem? Bei welcher Größe tritt es auf?
 
Die Frage ist auch warum das Zeichnen ohne Image lange dauert. Von welcher Größenordnung Linien reden wir, und wieviele davon sind gleichzeitig sichtbar? Musst du zum zeichnen noch etwas berechnen, oder ist alles ready to use?
 
Ich zeichne einen Audiograph. Und habe zur Zeit bis zu 5000 Koordinaten eingestellt ... Das habe ich gemacht damit ich skalieren kann (vergrößern bis zur einer gewissen Auflösung) ohne Daten vom Audiofile neu nachzuladen zu müssen.

Berechnen muss ich nur bei Größenänderung des Panels (also wenn sich this.getSize() ändert ) . Siehe unten.

Ich stimme dir schon zu , dass hier sicher Optimierungsmöglichkeiten sind. Aber mit dem BufferedImage geht das zeichnen rasend schnell!!!! Ich erlaube auch Selektion der Grafik usw. , d.h. bei MouseDrag wird der selektiere Bereich invertiert usw (ich kopiere da nur die Bitmap mit dem Grafen und zeichne per xor verknüpfung die selektion). ... und wenn ich da jedesmal den Grafen neu zeichen muss wie unten !? ..

Hier meine "langsamen" Operationen ( ich werde das morgen optimieren. U.a mit dem Vector und der Hashmap😉. Aber das wird nie so schnell werden wie mit dem Buffered Image - das weiß ich jetzt schon! )

Und danke euch für die Hilfsbereitschaft!!

Code:
      for(int i=1; i<m_lineVector.size(); i++)
      {
          x_old = x_new;
          y_old = y_new;

          x_stored = m_lineVector.elementAt(i);
          y_stored = m_lineHash.get( x_stored );

           x_new = (double)x_stored/(maxRes.getWidth()-1.0d ) * (d.getWidth()-1.0d);
          y_new = d.getHeight()-1.0d - y_stored * (d.getHeight()-1.0d);       

          // todo: clipping evtl beim kanal mischen oben
          
          g2image.draw( new Line2D.Double( x_old, y_old, x_new, y_new) ); 
      }


Wildcard hat gesagt.:
Die Frage ist auch warum das Zeichnen ohne Image lange dauert. Von welcher Größenordnung Linien reden wir, und wieviele davon sind gleichzeitig sichtbar? Musst du zum zeichnen noch etwas berechnen, oder ist alles ready to use?
 
Bingo!!
Die Option

Code:
java -Dsun.java2d.noddraw=true -jar "meinProg.jar"

schaltet die Verwendung von DirectDraw und Direct 3D aus (bzgl Java2D). Dann läuft alles wie geschmiert!!
Super brummfondel!! Was mich jedoch jetzt stört ist wieder die Systemabhängigkeit bzw. das man von "außen" wieder was einstellen muss! ... naja, jedenfalls hat dein Tipp mir eine Menge Sucherei erspart - da ich dachte, dass ich evtl nicht ganz sauber in paintComponent() arbeite ....!!


brummfondel hat gesagt.:
Das klingt, als würden da einige der Mal-Operationen vom falschen Chip erledigt, also entweder von der CPU im Grafikspeicher oder es wird von der CPU zuviel hin und her kopiert.

Versuch mal einige der Optionen von dort: http://java.sun.com/j2se/1.5.0/docs/guide/2d/flags.html
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben