# miese performance bei nem BufferedImage + repaint :(



## para_ (4. Aug 2007)

Hi, kann mir jemand sagen warum folgender code extrem langsam ist?
Wenn ich auf ein Feld klicke soll sich das terrain ändern, eben nur an der stelle wo ich hinklicke, aber wenn ich klicke dauerts ne sekunde oder so bis sich was tut...   (die karte ist 100x100 felder groß, bzw einstellbar, aber auch bei kleineren karten dauert das aktualisieren extrem lange)



```
//...
	BufferedImage map;
	int[][] mapAliases;
	int scale=20;
	int width; 	// in feldern, nicht in pixeln!
	int height; 
	
	public Map( int width, int height, int terrainAlias ) {
		this.width = width;
		this.height = height;
		this.setPreferredSize(new Dimension(width*scale, height*scale));
		this.setSize(new Dimension(width*scale, height*scale));
		map = new BufferedImage(scale*width, scale*height, BufferedImage.TYPE_3BYTE_BGR);
		mapAliases = new int[width][height];
		for ( int i=0; i<width; i++) {
			for ( int j=0; j<height; j++) {
				mapAliases[i][j] = -1;
			}
		}
	}
	
        // x und y sind Mouse positionen
	public void changeTile( int x, int y, int terrainAlias ) {
		x /= scale;
		y /= scale;
		if ( x<width && y<height && mapAliases[x][y] != terrainAlias) {
			mapAliases[x][y] = terrainAlias;
                        Graphics g = map.getGraphics();
			g.drawImage(MyGraphics.graphics.get(terrainAlias).getScaledInstance(scale, scale, BufferedImage.SCALE_FAST), x*scale, y*scale, null);
			// System.out.println(" changed something ");
			repaint();
		}
		else { 
			// System.out.println(" changed nothing ");
		}
	}
	
	public void paintComponent( Graphics g ) {
		g.setColor(Color.BLACK);
		g.fillRect(0,0,this.getPreferredSize().width, this.getPreferredSize().height);
		g.drawImage(map.getScaledInstance(width*scale, height*scale, 3), 0, 0, null);
	}
```

thx für alle möglichen verbesserungsvorschläge :$


----------



## Wildcard (4. Aug 2007)

wann rufst du changeTile auf?
Bilder zu skalieren ist immer sehr teuer.
Ausserdem hab ich schon nach diesem Snippet den Verdacht das du übelsten Foobar mit Graphics Objekten machst...


----------



## para_ (4. Aug 2007)

hm? was meinst du ich mach foobar mit graphics objekten? 

change tile wird aufgerufen wenn ich mit der maus klicke bzw dragge

die schlechte performance lag daran dass ich die gesamte map nochmal skaliere, was garnicht sein muss, war mein fehler

trotzdem würd mich intressieren was du meintest :$ würds gern besser machen


----------



## Marco13 (4. Aug 2007)

Die Zeile
Graphics g = map.getGraphics(); 
ist ein starkes Indiz für einen bekannten Fehler: 

Vielleicht auch noch ein paar weitere Erklärungen dazu
http://java.sun.com/products/jfc/tsc/articles/painting/
("Good Painting Code Is the Key to App Performance" :wink: )


Und hier noch das (recht ausführliche) foreneigene Tutorial:
http://www.java-forum.org/de/viewtopic.php?p=278630&highlight=#278630

Die Quintessenz ist: ALLES was jemals gezeichnet wird, muss in paintComponent gezeichnet werden (bzw. in Methoden, die von paintComponent aus aufgerufen werden). Man sollte also *NIE getGraphics aufrufen!!!* (das kann man nicht deutlich genug sagen :wink: ).


----------



## para_ (4. Aug 2007)

ok danke  dann schau ich mir die erklärungen und tutorials an, ich dachte nur weil das BufferedImage map ja nicht angezeigt wird wenn draufgemalt wird kann ichs ja machen


----------



## Marco13 (4. Aug 2007)

*Kommando zurück! Man darf DOCH getGraphics aufrufen!*

Aber NUR, wenn es auf einem BuffereImage aufgerufen wird. Die Klasse "Component" hat auch eine Methode getGraphics, und die sollte man NICHT aufrufen. Auf einem BufferedImage ist getGraphics vollkommen in Ordnung. (Sorry,ich hatte nur gesehen, dass die Klasse "Map" heißt, und bin davon ausgegangen, dass es eine Component ist - dass die Klasse Map aber ein Field "map" enthält, das ein BufferedImage ist, hatte ich übersehen   )
[/u][/b]


----------



## Wildcard (4. Aug 2007)

Marco13 hat gesagt.:
			
		

> *Kommando zurück! Man darf DOCH getGraphics aufrufen!*
> 
> Aber NUR, wenn es auf einem BuffereImage aufgerufen wird.


Auch in BufferedImage ist die nur zur Abwärtskompatibilität. Stattdessen createGraphics aufrufen.


----------

