# repaint()-Problem



## Lionhead (31. Mai 2004)

Wie kann man gezeichnete Images von einer repaint()-Anweisung auschliessen? Also wenn ich jetzt n Bild zeichne (drawImage(....)) kann ich irgendwie erreichen dass dieses nicht repainted wird. (brauch für n Hintergrund des dauert ewig wenn der bei jedem Aufruf der paint-Methode neu gezeichnet wird)


----------



## Beni (31. Mai 2004)

Wie meinst du das? Du baust jedes mal das Bild neu auf? Dann mach ein boolean "imagePainted" und eine schöne if-Abfrage.

@conehead
Spam wird hier gnadenlos gelöscht


----------



## Lionhead (4. Jun 2004)

Wenn ich in der paint-Methode eine if Abfrage um das zu zeichnende Bild mache dann wird es ja immer gezeichnet wenn die Bedingung erfüllt ist . Das heisst wenn ich repaint() mache dann wird dass Hintergrund-Bild ja trotzdem noch jedesmal neu geladen (bei jedem repaint() ) oder es erscheint gar nicht wenn die Bedingung nicht erfüllt ist.
Was ich wissen wollte wie kann ich erreichen das mein Hintergrund-Bild beim aufruf der repaint()-Methode nicht neu aufgebaut wird sondern einfach bleibt. gibts da vielleicht irgendwas was man beim Image-Objekt setzten kann (z.B irgendein boolean) ob es vom repaint() btroffen sein soll oder net.


----------



## Xenophon (4. Jun 2004)

Das mit der if-Abfrage sollte schon funktionieren. Mach Dir eine Variable "boolean imagePainted = flase;". Bei "if(!imagePainted)" gehst Du in den Zweig zum zeichnen und setzt sie dort gleich mit auf true. So sollte nur beim ersten Durchgang gezeichnet werden und wenn Du die Variable selber wieder auf false setzt.


----------



## K-Man (4. Jun 2004)

Ich glaube er meint, dass er ein bereits gezeichnetes Bild nicht mehr zeichnen lassen will.
Er lädt zum Beispiel ein Image in ein Frame. Wenn er das zweite Image lädt, dann will er nicht, dass das erste nochmal gezeichnet wird. Bei repaint wird aber alles neu gezeichnet. Macht er es nun mit dem boolean, dann zeichnet er das Bild zwar nicht mehr, aber es verschwindet auch vom Frame.
Ich kann mir nur vorstellen, dass du jedes Bild in einer eigenen Component zeichnest und nur diese repaintest, wenn sich da was verändert. Andernfalls kann man glaub ich bestimmen, welcher bereich "zeichenbar" ist. Aber ich weiß nicht, ob dann evtl andere Bilder, die somit aus dem Zeichenbereich fallen, gelöscht werden. Mit "zeichenbar" mein ich zb, dass man nicht über die Menüleiste zeichnen kann, da es nicht im Clipping-Bereich liegt...oder wie man das gleich wieder nennt


----------



## Lionhead (4. Jun 2004)

Genau dass mein ich K-man. Gibts vielleicht so ne repaint -Mthode mit der man nur einen bestimmten Bereich repainten kann? Oder kann ich z.B etwas in ein Panel zeichnen und dann irgendwie das Panel repainten?


----------



## Beni (4. Jun 2004)

Es gibt die hier: repaint( long time, int x, int y, int w, int h)

Aber falls das wirklich so lange geht, ist vielleicht sonst was krum.
Evtl. würde es sich lohnen, wenn du mal kurz deine paint-Methode postest.

mfg Beni


----------



## Lionhead (4. Jun 2004)

Vergiss es die ist riesig, dass mit dem bestimmten Bereich repainten ist schon nicht schlecht. aber das hilft mir bei meinem Problem nicht viel weiter...  Ich möchte ja ein Image als Hintergrund auf dass zeichne ich dann Spielfiguren u.s.w (iss fürn Spiel). aber wenn ich dann repainte sollen nur die Spielfiguren repainted werden nicht dass Hintergrund-Bild! Da dass recht groß ist dauert des ewig. Was ich jetzt wissen wollte Kann man ein Image irgendwie vom repaint ausschliesen so das es nicht neugezeichnet wird aber bleibt! Schwere Frage ich weiss aber ein klares nein is auch ok.


----------



## Beni (4. Jun 2004)

Ich frage mich, ob wir aneinander vorbeireden.
Ich verstehe unter "Bild zeichnen" diesen Befehl:

```
Graphics g = ...
Image img = ...
g.drawImage( img, 0, 0, this ); // oder so ähnlich
```
Aber nach meiner Erfahrung ist das nicht allzu schlecht.  ???:L 

Und es lässt sich nicht umgehen. Um die Figuren an ihren neuen Position zu zeichnen, muss das Panel ja zuerst gelöscht werden. (Ansonsten würden sie eine schöne Spur hinter sich herziehen...).

Ich missverstehen dich?


----------



## L-ectron-X (5. Jun 2004)

Versuche doch mal das Bild zu komprimieren, oder die Pixeldichte (dpi) herunterzusetzen, dann wird das Bild schneller geladen. Ansonsten kann man das Bild in ein Offscreen-Image (Speicher-Bild) laden, dass man schneller zur Verfügung hat. (Ich hab's mal irgendwo gelesen und hier auch schon mal gepostet)
Geht es nur ums Zeichnen, oder auch ums Laden? Beim Laden kannst Du dann auch den MediaTracker verwenden.
Eine Anwendung, die aber Bilder von der lokalen Festplatte läd, sollte damit aber keine Probleme haben.


----------



## K-Man (6. Jun 2004)

Du kannst dein Problem vielleicht umgehen. Du teilst dein Bild in kleine Einzelbilder. Diese fügst du in deinem Fenster zusammen. Beim repainten musst du halt dann abfragen, welche dieser Einzelbilder neu gezeichnet werden müssen. Den Rest kannst du dann aussließen. Du musst aber noch die update-Methode zusätzlich zur paint-Methode überschreiben. Machst du das nicht, dann wird alles gelöscht.
Auf gut deutsch:
Du teilst deinen Hintergrund in 20 Bilder. Beim nächsten Bild stellst du fest, dass du nur die Bilder 10, 11 und 12 neuzeichnen musst. Deine update-Methode löscht nur die Bilder 10, 11 und 12. Paint zeichnet jetzt nur diese Bilder und schon musst du deutlich weniger neuzeichnen, als normal.

Update sieht normal so aus:

```
public void update(Graphics g)
{
    g.setColor(getBackground());
    g.fillRect(0, 0, width, height);
    g.setColor(getForeground());
    paint(g);
}
```
Hier wird das komplette Fenster neu gezeichnet. Du überschreibst die Methode, damit sie nur noch die relevanten Teile des Fensters löscht. Die paint-Methode zeichnet jetzt genau diese Bilder neu.

Anmerkung:
Ich hab dieses Verfahren noch nicht ausprobiert. Ist mir jetzt grad so spontan eingefallen. Kann also nicht versprechen, dass es was nützt. Klingt aber schon mal vielversprechend. Was sagen die anderen dazu? Würd micht übrigens interessieren, ob es was bringt


----------



## K-Man (7. Jun 2004)

Wo sind denn die Profi(e)s? 
Mich würde auch mal interessieren, was ihr zu meiner Idee halten. Ist die für die Katz oder vielleicht doch anwendbar?


----------



## K-Man (7. Jun 2004)

Mir ist noch was eingefallen. Man kann ja zwei Components übereinanderlagern. Das Hintere hat das Hintergrundbild und das Vordere ist durchsichtbar und zeichnet die Spielfigur.
Mich interessiert eigentlich immer noch, ob ich Mist erzähle, oder nicht....


----------



## Beni (7. Jun 2004)

K-Man hat gesagt.:
			
		

> Mich interessiert eigentlich immer noch, ob ich Mist erzähle, oder nicht....


Meine ganz klar und sicher sehr hilfreiche Antwort: _keine Ahnung_  :wink: 

Allerdings finde ich es immer noch komisch, dass man solange benötigt um ein Bild zu zeichnen...  ???:L


----------



## L-ectron-X (7. Jun 2004)

Ich finde die Idee gut und denke auch, dass sie funktioniert. Wenn man sich die Doku der paint()-Methode mal anschaut:


			
				API-Documentation - java.awt.Component#paint(Graphics g) hat gesagt.:
			
		

> ...
> This method is called when the contents of the component should be painted; such as when the component is first being shown or is damaged and in need of repair.
> ...


Sinn gemäß: Diese Methode wird aufgerufen, wenn der Inhalt einer Component gezeichnet werden sollte; z.B. wenn die Component zum ersten Mal gezeichnet werden soll oder sie beschädigt ist und eine Reparatur benötigt.

Das hört sich zumindest so an, wie K-Man es sich dachte. Und ich denke mal weiter...
Wenn man nun in der update()-Methode den Bereich löscht, der neu gezeichnet werden soll, müsste die paint()-Methode nur die neu zu zeichnenden Bilder zeichnen.

@Lionhead: Wie lang (in kB) ist das Bild, was Du laden und zeichnen möchtest?


----------



## K-Man (7. Jun 2004)

Da fällt mir gerade auf, dass man paintComponent überschreiben muss, nicht paint. Wir sind ja hier im swing-Bereich und nicht im awt


----------



## Lionhead (10. Jun 2004)

Ich blicks solangsam net mehr... :autsch: 
Kann man den Hintergrund net einfach mit der setBackground-Methode setzten, der man ein Image übergibt. Der Background wird ja sowieso nicht repainted , dann wär mein Problem gelöst.


----------



## K-Man (11. Jun 2004)

Lionhead hat gesagt.:
			
		

> Ich blicks solangsam net mehr... :autsch:
> Kann man den Hintergrund net einfach mit der setBackground-Methode setzten, der man ein Image übergibt. Der Background wird ja sowieso nicht repainted , dann wär mein Problem gelöst.


Mit setBackground() kannst du nur die Farbe des Hintergrundes bestimmen. Du kannst kein Image übergeben...


----------



## L-ectron-X (11. Jun 2004)

Eigentlich doch. Mit einem Offscreen-Image könnte es funktionieren.

```
Graphics g; 
Image hintergrund; 
... 
public void init() { 
... 
  hintergrund = createImage(breite, hoehe); 
  g = hintergrund.getGraphics(); 
} 

public void update(Graphics g) { 
  g.setColor(getBackground()); 
  g.fillRect(x, y, breite, hoehe);
  g.setColor(getForeground()); 
  paint(g); 
} 

public void paint(Graphics g) { 
  //zeichnen 
  //zum Schluss Offscreen-Image auf die Oberfläche kopieren 
  g.drawImage(hintergrund, 0, 0, this); 
}
```
In diesem Beispiel wird ein Image-Objekt mit createImage() erzeugt und dem Graphics-Objekt (Zeichenfläche) übergeben. Das kann auch ein anderes Image-Objekt sein, welches von wo anders beschafft wird. Dann muss aber die update()-Methode angepasst werden.


----------

