2009-02-19 7 views
5

Ich habe eine Routine, die ein wahnsinnig großes Diagramm in einem Bildlauffenster malt. Es ist zu groß, um es zu malen, bevor es zum Scrollpanel hinzugefügt wird - die menory-Anforderungen wären mehrere Gigs.Warum führt meine jscrollpane beim Java Swing zu seltsamen Farbaufrufen?

Aufgrund der Größe des Diagramms rende ich das Diagramm innerhalb der Paint-Methode des untergeordneten Bildlaufbereichs. Das funktioniert gut, aber ich merke, dass jedes Mal, wenn eine Bildlaufleiste bewegt wird, meine Malroutine zweimal aufgerufen wird - einmal mit einem Ausschnitt, der gleich dem unbedeckten Bereich ist, und ein zweites Mal mit dem Ausschnitt rect, der den Abmessungen des Ansichtsfensters entspricht .

Zum Beispiel, wenn mein Ansichtsfenster ist 245x195 & ich um 3 Pixel nach unten scrollen meine Farbe Routine mit g.getClipBounds() Satz aufgerufen wird, wie folgt:

java.awt.Rectangle[x=0,y=195,width=245,height=3] 
java.awt.Rectangle[x=0,y=3,width=245,height=195] 

... weil ich das in der Farbe Routine machen wird Flimmern verursacht (Ich mache meine Kälber so schnell ich kann, aber es gibt ein kleines bisschen Verzögerung, denke ich). Fragen:

  1. Wer weiß, wie die zweite Farbe Anruf zu verhindern? Dies ist plain-jane JScrollPane Sachen, die ich hier mache - ich habe eine Komponente, ich füge es dem Scrollpane hinzu, ich füge das Scrollpane zu einer Elternkomponente hinzu. Sie können dieses Verhalten sogar in der ersten Bildscrolldemo @the swing tutorial sehen.

  2. Wenn die Antwort auf # 1 ist "Nein": kann jemand einen guten Weg vorstellen, damit umzugehen? Sollte ich in eine Art Bildpuffer malen, verfolgen Sie die letzten Farbaufrufe & Kopieren Sie das Bild wo möglich? Ich kann mir nicht vorstellen, dass dies viel schneller als das Rendern ist, aber jede Einsicht wird geschätzt :-)

Antwort

4

Ich bin auf dieses Problem in der .NET-Welt gestoßen. Doppelpufferung sollte Ihr Problem lösen.

Wenn Sie direkt auf eine Oberfläche rendern, die auf dem Bildschirm angezeigt wird, haben Sie keine Kontrolle darüber, wann das "Anzeigen" tatsächlich stattfindet. In der Regel passiert Folgendes: Sie beginnen mit dem Rendern, das noch nicht fertig gestellte Bild wird auf dem Bildschirm angezeigt, Sie beenden das Rendern, und dann wird das schließlich auf dem Bildschirm angezeigt.

Wenn Sie Ihre Rendering-Logik durch Löschen einer Hintergrundfarbe beginnen, wird dies wie ein Blitz angezeigt. Die doppelte Pufferung verhindert dies, da sie immer von einem abgeschlossenen Rendervorgang angezeigt wird. Das Schlimmste, was passieren könnte, ist ein leichtes "Reißen", aber das macht sich nur in schnell wechselnden Animationen bemerkbar.

Auch wenn Sie nur einen Teil eines gigantischen Bildes rendern möchten, können Sie diese Technik trotzdem verwenden. Rendern Sie einfach das, was Sie brauchen, auf eine Fläche außerhalb des Bildschirms (die Größe des gewünschten sichtbaren Bereichs). Und dann, wenn Sie fertig sind, zeichnen Sie das gesamte Bild auf einen Blick auf Ihre Display-Oberfläche auf einen Schlag.

+0

mein einziges Problem ist, dass ich nicht das gesamte Bild puffern kann - es ist zu groß. Was bedeutet, ich muss gepufferte Abschnitte behalten, wie sie gezeichnet werden, überprüfen Sie für Abdeckung, wenn ich aufgerufen werde, zu malen() & nähen Sie sie zusammen wie benötigt. Ich denke, ich werde es eine Chance geben, aber ich werde warten, um zu sehen, ob jemand andere Ideen hat –

+0

Nun, doppelte Pufferung kann immer noch ins Spiel kommen. Rendern Sie einfach, was Sie brauchen, auf einer Off-Screen-Oberfläche (die Größe des sichtbaren Teils). Und dann, wenn Sie fertig sind, zeichnen Sie das gesamte Bild auf einen Blick auf Ihre Display-Oberfläche auf einen Schlag. – colithium

+0

eigentlich funktioniert das.Danke :-) Scrolling ist ein bisschen langsamer, aber das Flimmern ist weg. Sorry, ich habe es zuerst nicht verstanden - meine Dummheit war für deine Beharrlichkeit nicht geeignet ;-) –

Verwandte Themen