# Graphics Objekt ändern



## rinc (18. Sep 2006)

Hallo,
ich habe ein Problem welches ich einfach nicht lösen kann:

Ich brauche in einem Programm ein Panel mit x mal y Punkten (ca. 200 x 300).
Die Farbe von jedem dieser Punkte soll später geändert werden können.

Unten habe ich zwei java Klassen eingefügt, welche das Problem hoffentlich verdeutlichen.
Natürlich funktioniert das Ganze noch nicht und es ist auch nur ein Ansatz.

Das Konkrete Problem in meinem Versuch ist, dass ich der _changeColor(int i, Color c)_ Methode nicht das Graphics Objekt übergeben kann. 
Die Sache wäre einfach wenn man _changeColor(int i, Color c, Graphics g )_ schreiben könnte.

Hat jemand einen Lösungsvorschlag oder eine bessere Idee?


GraphicsPanel.java

```
package Test01;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JPanel;

public class GraphicsPanel extends JPanel {
	private static final long serialVersionUID = 1L;
	private Shape dots[] = new Shape[4];
	private Graphics2D g2;
	
	/**
	 * Zeichnet den Hintergrund und ein paar Punkte
	 */
	public void paintComponent(Graphics g) {
		//alle shapes initialisieren
		Shape rect = new Rectangle2D.Double(0.0, 0.0, 80.0, 80.0);
		dots[0] = new Ellipse2D.Double(20.0, 20.0, 15.0, 15.0);
		dots[1] = new Ellipse2D.Double(20.0, 60.0, 15.0, 15.0);
		dots[2] = new Ellipse2D.Double(60.0, 20.0, 15.0, 15.0);
		dots[3] = new Ellipse2D.Double(60.0, 60.0, 15.0, 15.0);

		//hintergrund zeichnen
		g2 = (Graphics2D) g;
		g2.setColor(Color.red);
		g2.fill(rect);

		//Punkte zeichnen
		g2.setColor(Color.blue);
		g2.fill(dots[0]);
		g2.fill(dots[1]);
		g2.fill(dots[2]);
		g2.fill(dots[3]);
	}
	
	/**
	 * sollte eigentlich die Farbe von einem bestimmten Punkt ändern.
	 * @param i - bezeichnet den entsprechenden Punkt
	 * @param c - die neue Farbe.
	 */
	public void changeColor(int i, Color c) {
		//soll die Farbe von dots[i] aendern!!!
		g2.setColor(c);
		g2.fill(dots[i]);
	}
}
```

DisplayMain.java

```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

public class DisplayMain implements ActionListener {
	private static DisplayMain displayMain = new DisplayMain();
	private static GraphicsPanel graphicsPanel = new GraphicsPanel();
	
	public static void main(String[] args) {
		JFrame f = new JFrame("Frame");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		//Button zum Testen
		JButton button1 = new JButton("Change Color");
		button1.addActionListener(displayMain);
		f.add(button1, BorderLayout.NORTH);

		//Das Panel mit den Punkten
//		f.add(new GraphicsPanel(), BorderLayout.CENTER);
		f.add(graphicsPanel, BorderLayout.CENTER);
		
		f.setSize(160, 200);
		f.setVisible(true);
	}

	public void actionPerformed(ActionEvent ae) {
		//wenn auf den Button gedrückt wird, soll die Farbe von einem Punkt geändert werden.
		graphicsPanel.changeColor(2, Color.yellow);
	}
}
```


(Der Sinn dieses Programms ist dass für Optische Experimente die Farbe der einzelnen Punkte sehr schnell geändert werden können soll. )


----------



## rinc (18. Sep 2006)

Die Lösung wäre:


```
public void changeColor(int i, Color c, Graphics g) {
		//soll die Farbe von dots[i] aendern!!!
		Graphics2D g2 = (Graphics2D) g;
		g2.setColor(c);
		g2.fill(dots[i]);
	}
```

nur leider kann die 


```
public void actionPerformed(ActionEvent ae) {
		//wenn auf den Button gedrückt wird, soll die Farbe von einem Punkt geändert werden.
		graphicsPanel.changeColor(2, Color.yellow);
	}
```

Methode ja "Graphics g" nicht übergeben


*HILFE, BITTE!!!*


----------



## Leroy42 (18. Sep 2006)

Du mußt g.setColor(...) in der paintComponent-Methode setzen
und in der actionPerformed-Methode ein repaint() aufrufen:

Etwa so:


```
private Color color = Color.red;
...
public void paintComponent(Graphics g) {
  super.paintComponent(g); // Nicht vergessen!
  g.setColor(color);
  ...
}
...
public void actionPerformed(ActionEvent e) {
  color = Color.yellow();
  graphicsPanel.repaint();
}
```


----------



## rinc (19. Sep 2006)

Danke für deine Antwort,

leider funktioniert das noch nicht so richtig  
Konkret gibt es folgende Probleme:

1)    wenn ich _graphicsPanel.repaint();_ in der _actionPerformed_ Methode aufrufe, wird alles (der Button und die Grafik) noch mal gezeichnet und zwar etwas nach unten versetzt.
2)    wenn ich _g.setColor(color);_ aufrufe werden alle Punkte die danach gezeichnet werden in der entsprechenden Farbe gezeichnet. Der Witz bei dem Programm ist aber dass alle Punkte verschiedene Farben haben können. 
3)    Da es sehr viele Punkte sind wollte ich außerdem nur einen Punkt neu Zeichen und nicht die ganze Grafik.
4)    Wenn möglich wollte ich auch auf ein Array mit einer Farbe für jeden Punkt verzichten, das würde die Sache mit _graphicsPanel.repaint();_ zwar relativ einfach machen, ist aber nicht der Sinn des Ganzen.

Viele Grüße
rinc


----------



## SlaterB (19. Sep 2006)

vielleicht besser frame-repaint() aufrufen,

vielleicht hilft dir dieser Thread zur allgemeinen Übersicht über die Zeichen-Probleme weiter:
http://www.java-forum.org/de/viewtopic.php?t=36500


----------



## rinc (19. Sep 2006)

* Vielen Dank * das war die Lösung!!!

Jetzt funktioniert es, mein Problem ist mit _Graphics g = getGraphics();_ gelöst:


```
public void changeColor(int i, Color c) {
		//soll die Farbe von dots[i] aendern!!!
		Graphics g = getGraphics(); 
		Graphics2D g2 = (Graphics2D) g;
		g2.setColor(c);
		g2.fill(dots[i]);
	}
```

jetzt gibt es nur noch einen kleinen Haken: 
Wenn ich den Punkt neu zeichne, wird er einfach über den schon vorhandenen Punkt gezeichnet, also kann es passieren, dass noch ein paar Pixel in der alten Farbe zu sehen sind. Das ist nicht so schlimm, es wäre aber schöner wenn entweder der alte Punkt vorher gelöst würde oder er einfach mit der neuen Farbe noch mal gezeichnet würde.

Geht das?


----------



## Wildcard (19. Sep 2006)

In dem Thread stand doch ganz klar das man getGraphics *nicht* benutzen soll  :noe:


----------



## rinc (20. Sep 2006)

Uuups, Du hasst recht, da steht dass man nur in der _paint()_ bzw.  _paintComponent()_ Methode zeichnen soll. Aber dann müsste ich ja andauernd die ganze Grafik neu zeichnen und das dauert eindeutig zu lange, nämlich ein paar Sekunden. Ich muss aber ca. 25-mal in der Sekunde neu zeichnen können.


----------



## SlaterB (20. Sep 2006)

niemand behauptet, dass Swing eine leistungsfähige Grafik-Engine ist 
25x pro Sekunde ist ja schon Kino-Qualität, kann man die einzelnen Änderungen dann überhaupt alle wahrnehmen oder ein paar zusammenfassen?

du kannst dann natürlich versuchen, mit diversen Tricks trotzdem weiterzukommen,

vielleicht hilft auch das Verfahren 'Zeichnen auf Bild-Objekt + in Paint nur das Bild malen'


----------



## Wildcard (20. Sep 2006)

SlaterB hat gesagt.:
			
		

> niemand behauptet, dass Swing eine leistungsfähige Grafik-Engine ist


Ich behaupte genau das. Swing ist nicht nur leistungsfähig, sondern vieleicht auch das flexibelste GUI Toolkit überhaupt.


----------



## SlaterB (20. Sep 2006)

ja ne GUI, bei der nur alle 5 Sekunden eine Aktualisierung ist,
aber doch wohl kaum geeignet für Halflife oder so,
mit jPanel.repaint() für jedes Frame


----------



## Wildcard (20. Sep 2006)

Für Spiele muss man active Renering verwenden, da benutzt man kein repaint.
Für 3D spiele ist Swing nicht konzipiert (SWT zB auch nicht). Dafür nimmt man dann Bibliotheken mit OpenGL.
Swing ist ein Toolkit für Desktop Applikationen, und diese Aufgabe erfüllt es jetzt schon hervorragend, und die Entwicklung ist noch lange nicht beended.


----------

