Großes "Koordinatenraster" effizient zeichnen

simon1389

Grünschnabel
Hallo miteinander :)

Bin jetzt seit 3 oder 4 Tagen am googeln und suchen.. komme aber auf keinen wirklich grünen Zweig.

Das Problem:
Ich hab ein Programm mit einer unter Umständen ziemlich großen Zeichenfläche (JPanel). Dadrauf werden Objekte als Shapes gezeichnet.
Diese Objekte kann ich jetzt per Knopfdruck an einem Raster ausrichten.
Jetzt möchte ich in dieser Zeichenfläche das Raster allerdings auch sichtbar machen, also die Gitternetzlinien zeichnen.
Bei einer kleinen Zeichenfläche ist das noch nicht weiter schlimm und geht recht flüssig.

Das Problem kommt wenn meine Zeichenfläche sehr groß wird. Dann muss ich ja auch bei jedem paintComponent aufruf (die ich überschrieben habe) die Gitternetzlinien neu zeichnen (zb wenn man zoomt oder Objekte aus der Zeichenfläche rausschiebt und diese dann vergrößert werden muss)). Anfangs hatte ich das noch ziemlich bescheuert in zwei while-Schleifen direkt in der paintComponent gemacht.. Bin jetzt aber schon soweit, dass ich immer wenn eine Neuzeichnung des Raster notwendig ist, das in BufferedImage zeichne und dann nurnoch das BufferedImage in der paintComponent zeichnen lasse.
Geht schon wesentlich besser, allerdings immernoch nicht ganz zufriedenstellend.
Das ist die Methode, in der das Raster in ein BufferedImage gezeichnet wird die wiegesagt beim zoomen und verschieben von Elementen aufgerufen wird (Unter Umständen auch beim hinzufügen von Elementen, weil diese aus der Zeichenfläche rausragen):

Code:
public void paintRasterToImage() {
		if (refreshRaster) {
		raster = new BufferedImage(Math.max(800, Math.max(this.getWidth(),
				(int) this.getVisibleRect().getWidth())),
				Math.max(800, Math.max(this.getHeight(), (int) this
						.getVisibleRect().getHeight())),
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g2d = raster.createGraphics();
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);

		int pictureWidth = raster.getWidth();
		int pictureHeight = raster.getHeight();

		int counter = 1;
		g2d.setColor(Color.white);
		g2d.fillRect(0, 0, pictureWidth, pictureHeight);
		g2d.setColor(Color.black);
		g2d.scale(tabPane.getZoomFactor(), tabPane.getZoomFactor());
		g2d.setStroke(s3);
		while (counter
				* (tabPane.getZoomFactor() * UtilityViewConstants.RASTER_SIZE) < pictureWidth) {
			g2d.drawLine(counter * UtilityViewConstants.RASTER_SIZE, 0, counter
					* UtilityViewConstants.RASTER_SIZE,
					(int) (pictureHeight / tabPane.getZoomFactor()));
			counter++;
		}

		counter = 1;
		while (counter
				* (tabPane.getZoomFactor() * UtilityViewConstants.RASTER_SIZE) < pictureHeight) {
			g2d.drawLine(0, counter * UtilityViewConstants.RASTER_SIZE,
					(int) (pictureWidth / tabPane.getZoomFactor()), counter
							* UtilityViewConstants.RASTER_SIZE);
			counter++;
		}
		g2d.dispose();
		}
	}

In den while-Schleifen rechne ich mir nur aus wieviele Linien ich zeichnen muss und wie lang die werden müssen ;-)

Hab schon versucht das Weichzeichnen rauszulassen. Das bringt aber auch keine Verbesserung...
Das Problem ist einfach gesagt, dass ich nicht am Anfang ein großes Image erzeugen kann, weil selbst dieses große Image dann unter Umständen irgendwann zu klein wird ;-)
Zoomen tu ich einfach nur über die scale-Methode von Graphics2D direkt in der paintComponent.. (falls das wichtig ist)

Ich denke dass es da doch irgendeine einfachere Lösung geben muss für sein ein "banales" Problem?

Ich hoffe ihr könnt mir einen Tipp geben :-)

LG
 
Hi,

also wenn das Raster nicht all zu "schön" aussehen muss, kannst du prinzipiell alle RenderingHint-Optionen auf ein Minimum runter stellen. Dann geht das zeichnen um einiges schneller.
Wenn du das Raster aber schon in ein Image reinmalst, kannst du doch auch gleich das Image nehmen und da ranzoomen. Dann brauchst du das Raster nur einmal - evtl. auch auf voller Qualität - zeichnen lassen und kannst das immer wieder her nehmen.

Gruß

Fabio
 
Zurück