Swing 64bit Problem mit paint/paintComponent

Lipro

Mitglied
Hallo zusammen,

ich hab folgendes Problem, das nur unter Windows 7/64bit auftritt (und das in einer größeren Anwendung isoliert wurde):

Klickt man im folgenden Beispiel ins rechte (rote) JPanel wird der Inhalt des linken (grünen) JPanel ins rechte JPanel gezeichnet, obwohl die Methode paintComponent in diesem Fall eigentlich keinerlei Aktionen setzen sollte. Unter Windows 7/32bit ist wie gesagt alles "normal".

Java:
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

class JPanel2 extends JPanel { 
  JPanel2 () {
    setBackground(Color.GREEN);
  }
}
class JPanel1 extends JPanel {
  boolean mouseClicked=false;
  JPanel1() {
    setBackground(Color.RED);
    addMouseListener(new MouseAdapter() {  
      @Override public void mouseClicked(MouseEvent e) {
        mouseClicked=true;
        repaint();
      }
    });  
  }
  public void paintComponent(Graphics g) {
    if (!mouseClicked) super.paintComponent(g);
  }
}
public class PaintTest { 
  public static void main( String[] args ) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    f.setSize(300,200);
    f.setLayout(new GridLayout(0,2));
    f.add(new JPanel2());
    f.add(new JPanel1());
    f.setVisible( true ); 
  }    
}

Hat jemand eine Idee, warum das passiert. Vorab schon herzlichen Dank für eure Antworten!
 
Kann ich so direkt nicht nachvollziehen. Wenn man statt repaint() schreibt [c]getParent().repaint();[/c] sieht man eine Änderung zu hellgrauem Hintergrund, aber allgemein: Wenn super.paintComponent nicht gemacht wird, ist der Inhalt des Panels quasi "undefiniert"... (ist ungenau, aber ... ich weiß nicht, was du erwartest...)
 
Die Anwendung aus der ich das Problem isoliert habe, hat folgende Funktion:

Ich will mit der Maus in ein Panel zeichnen (das wäre im Codeschnippsel das rote), weitere Panele enthalten Tools wie Farbpaletten, etc. Zeichnen hab ich so implementiert, dass die jeweiligen Mausclicks, -drags, etc. ERGÄNZEND zum bis dahin existierenden Bild gezeichnet werden. Das würde im else-Zweig von if (!mouseClicked) super.paintComponent(g); passieren. super.paintComponent(g) wird nur aufgerufen beim Programmstart, beim Neuladen eines Bildes etc. um den Hintergrund zu löschen.

Sobald ich im fertigen Programm in das Zeichenpanel klicke, wird mir (nur auf 46bit Rechnern) der Inhalt des links davon liegenden Werkzeugpanels (das wäre dann das grüne) in das Zeichenpanel reingezeichnet.

Der versuchte Lösungsansatz immer das ganze Bild neuzuzeichnen (also bei jedem Mausklick super.paintComponent und dann alle Bilddsegmente neuzeichnen) ist definitiv zu langsam.
 
Man muss sich damit abfinden: In der paintComponent MUSS alles gezeichnet werden (ggf. kann man die ClipBounds des Graphics2D verwenden), weil es ja sein kann, dass ein anderes Fenster das aktuelle verdeckt hat - dann ist das bisher gezeichnete einfach "weg"...
Das super.paintComponent sollte nicht lange dauern, weil dort nur mit fillRect der Hintergrund gecleart wird. Gibt's einen Grund, warum das so langsam wird? Was für ein Bild wird dort (wie) gezeichnet?
 
hallo marco13 ... erstmal danke für's Auseinandersetzen mit meinem Problem!

super.paintComponent ist nicht das Performanceproblem, verursacht es aber indirekt, weil es die Zeichenfläche löscht und so das permanente Neuzeichnen z.B. einer Freihandfigur erfordert, die ja aus einer sehr großen Menge von Punkten und Liniensegmenten bestehen kann (ich speichere das Bild als Vektorgrafik).

Falls super.paintComponent bei jeder Mausaktivität (die Zeichenoperationen auslöst) ausgeführt werden muss, wäre das Grundkonzept (Fläche löschen mit super.paintComponent, dann additives Zeichnen analog zur Mausaktivität) also nicht praktikabel und funktioniert auf 32bit Rechnern eher zufällig. Richtig ???
 
Ja, dass es auf deinem 32 Bit Rechner funktioniert ist Zufall. Die übliche Lösung für dein Problem ist: die Vektorgrafik auf ein Image (z.B. BufferedImage) zeichnen, und in paintComponent einfach dieses Image anzeigen. Das Image musst du natürlich nur dann aktualisieren, wenn es neue Elemente gibt.
 
Dieses "additive Zeichnen" funktioniert wohl tatsächlich eher zufällig, aber ich würde das weniger mit 32bit-Rechnern als vielmehr mit Betriebssystem und Grafikkarte/Treiber in verbindung bringen. In jedem Fall ist es keine zuverlässige Lösung.

Aber man könnte das "additive Zeichnen" nachbauen. Ein legitimer Ansatz ist es, nicht direkt in das "Graphics" zu zeichnen, das man bei paintComponent bekommt, sondern in das Graphics eines BufferedImages - und in der paintComponent wird dann nurnoch dieses BufferedImage gezeichnet. Du könntest mal überlegen, ob das auf deinen Fall übertragbar sein könnte. GROB anskizziert, wie das aussehen könnte, hatte ich kürzlich in http://www.java-forum.org/awt-swing...nel-transparentem-hintergrund.html#post833696

EDIT: Den Thread raussuchen kann doch nicht so lange gedauert haben... :bahnhof:
 

Zurück
Oben