# Objekt bei Buttonklick zeichnen



## cr3m4 (22. Aug 2008)

Hallo Leute,

Ich habe diverse Methode die unterschiedliche Objekte zeichnen. Hier z.B. zwei Linien:


```
private Graphics paintLines(Graphics2D g2)
          {
                  /* parallele Linien zeichnen */
                  for(int i=startx; i<=stopx+thickness;i++)
                  {
                          g2.drawLine(i, starty, i, stopy);

                          g2.drawLine(i+50, starty, i+50, stopy);

                          g2.setColor(new Color(0, 0, 255));
                          g2.drawLine(i+50, starty, i+50, (stopPoint_jTable1.getRowHeight()+6)*7);
                          g2.setColor(Color.DARK_GRAY);
                  }
                return g2; 
          }
```


Und bei Klick auf einen Button soll dem Grafikpanel:


```
private JPanel getMapGrafikPanel() {
                  if(MapGrafikPanel == null) {
                          MapGrafikPanel = new JPanel();
                          Graphics2D g2 = (Graphics2D)g;
                          super.paintComponents( g2 );

                          paintLines(g2);
                          paint(MapGrafikPanel.getGraphics());       

                  }
                  return MapGrafikPanel;
          }
```

eine weitere Graphics-Komponente hinzugefügt werden.

nur  habe ich keinen Schimmer wie ich das anstellen soll. Ich dachte ursprünglich in etwa so:

```
Graphics g= panel.getGraphics();
g.draw...

panel.repaint();
```

aber hat keinerlei Auswirkung. Habe zwar nen Thread zu dem Tehma gefunden, der blieb jedoch unbeantwortet.


----------



## SlaterB (22. Aug 2008)

im Button machst du sowas wie 

toPaintList.add(new PaintSomething());
repaint();

und allein die paint-Methoden schaut dann in toPaintList nach und malt das neue,


einfache Regel: nie getGraphics(); aufrufen!
painten dürfen nur die paint-Methoden,
alle anderen dürften höchstens Daten-Objekte bereitstellen/ ändern, boolean-flag setzen usw.

wenn was nicht geht, dann poste idealerweise ein komplettes kleines Testprogramm


----------



## cr3m4 (22. Aug 2008)

ui ging aber flott die Antwort. werds deinen Ansatz gleich angehen. tnx


----------



## cr3m4 (22. Aug 2008)

ok also das mit der Paintlist is mir grad nicht geläufig. Soll ich eine Art JList erstellen und dann irgendwie die Paintmethoden reinpacken?


----------



## SlaterB (22. Aug 2008)

ich dachte an eine normale ArrayList mit Objekten, die ein Interface mit einer Methode paint() implementieren,

aber das ist beliebig von deinen Anforderungen abhängig,
wenn du nur ein bestimmtes Objekt hast dann kannst du auch nur das in einer Extra-Einzel-Variablen speichern,
im einfachsten Fall reicht ein boolean true/ false und die paint-Methode weiß dann schon, was zu tun ist,

von einfach bis komplex gibts da ein breites Spektrum an Möglichkeiten


----------



## cr3m4 (22. Aug 2008)

aha, ok muss ich mich erstmal mit Arraylist auseinandersetzen.


----------



## cr3m4 (22. Aug 2008)

So ganz komm ich mit der Listenmethoden noch nich klar.
Ich beschreib mal wie ich dachte dass es Funktioniert:

Zunächst habe ich in dem Panel auf dem gezeichnet werden soll die Arrayliste erstellt und wollte die zu zeichnenden Objekte hinzufügen:

```
private JPanel getMapGrafikPanel() {
                  if(MapGrafikPanel == null) {
                          MapGrafikPanel = new JPanel();
                          Graphics2D g2 = (Graphics2D)g;
                          super.paintComponents( g2 );

                          List<Graphics> list1 = new ArrayList<Graphics>();
                          list1.add(paintLines(g2));     

                  }
                  return MapGrafikPanel;
          }
```

und dann?

Ob du mir mal nen Beispielcode dazu geben kannst, wär klasse?


----------



## SlaterB (22. Aug 2008)

was haben da die Befehle
> Graphics2D g2 = (Graphics2D)g; 
>                          super.paintComponents( g2 ); 
zu suchen?
was liefert paintLines(g2) zurück?

wieso ist list1 lokal definiert?
wenn nach repaint() die paint-Methode darauf zugreifen soll, muss es doch wohl ein Klassenattribut sein,

was ist MapGrafikPanel?
Variablen immer klein schreiben,
wenn das das zu zeichnende einzelne Objekt ist, dann brauchst du wie gesagt keine Liste


----------



## cr3m4 (22. Aug 2008)

Ich habe einfach die zu Beginn des Threads geposteten Methoden verändert. Dachte dat reicht 

das 
	
	
	
	





```
Graphics2D g2 = (Graphics2D)g;
```
 ist doch quasi die Zeichnung die auf dem Zeichenbereich 
	
	
	
	





```
MapGrafikPanel
```
 dargestellt wird.


```
paintLines(g2)
```
liefert zwei  gezeichnete Linien an g2 zurück (siehe ersten Beitrag im Thread).

list1 ist lokal definiert weil ich kein Ahnung habe was ich damit eigentlich tun soll 

Mit der kleinschreibung haste recht, nit drauf geachtet, sorry.


----------



## SlaterB (22. Aug 2008)

wo kommt das g her?
ein Zeichenobjekt ist ein Objekt, welche eine Methode wie z.B. paint(Graphics g) implementiert, 
das g kommt erst beim paint-Aufruf vom System, das darf bei der Objekterstellung nicht bekannt sein, auch darf noch nichts gezeichnet werden,

erstelle erstmal eine normales Java-Programm, welches mit paint() oder paintComponent() irgendwas zeichnet,
danach kann man dann andere Dinge programmieren,
erst die Grundlagen..


----------



## Marco13 (22. Aug 2008)

Ja, so grob

```
interface Paintable 
{
    void paintOn(Graphics g);
}

class Lines implements Paintable
{
    public void paintOn(Graphics g) { male linien }
}

class PaintablePanel extends JPanel
{
    private List<Paintable> paintables = new ArrayList<Paintable>();

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        for (Paintable paintable : paintables)
        {
            paintable.paintOn(g);
        }
    }


    void addPaintable(Paintable paintable)
    {
        paintables.add(paintable);
        repaint();
    }
}

...
// Bei Buttonklick:
paintablePanel.addPaintable(new Lines());
```


----------



## cr3m4 (22. Aug 2008)

ok also ich habe mal eine Beispielanwendung als quasi neue Basis fürs Verständnis. Vielleicht kannst du anhand dieses Codes besser beschreiben was ich zu tun habe.


```
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;


public class NewJFrame extends javax.swing.JFrame {
	
	private static final long serialVersionUID = 1L;
	
	private JPanel zeichenbereich_jPanel;
	private JButton hinzufuegen_jButton;
	private JPanel button_jPanel;

	/**
	* Auto-generated main method to display this JFrame
	*/
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				NewJFrame inst = new NewJFrame();
				inst.setLocationRelativeTo(null);
				inst.setVisible(true);
			}
		});
	}
	
	public NewJFrame() {
		super();
		initGUI();
	}
	
	private void initGUI() {
		try {
			BorderLayout thisLayout = new BorderLayout();
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			getContentPane().setLayout(thisLayout);
			getContentPane().add(getZeichenbereich_jPanel(), BorderLayout.CENTER);
			getContentPane().add(getButton_jPanel(), BorderLayout.SOUTH);

			pack();
			setSize(400, 300);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/* Zeichenbereich in dem alle Graphics-Objekte dargestellt werden */
	private JPanel getZeichenbereich_jPanel()
	{
		zeichenbereich_jPanel = new JPanel()
		{
			private static final long serialVersionUID = 1L;

			public void paint( Graphics g ) 
			  { 
				  Graphics2D g2 = (Graphics2D)g;
				  super.paintComponents( g2 ); 
				  paintRect(g2);
			  }
		  };
		return zeichenbereich_jPanel;
	};
	
	/* Container für Button */
	private JPanel getButton_jPanel()
	{
		button_jPanel = new JPanel();

		button_jPanel.add(getHinzufuegen_jButton());
		return button_jPanel;
	};
	
	/* Button mit der Actionmethode */
	private JButton getHinzufuegen_jButton()
	{
		hinzufuegen_jButton = new JButton();
		hinzufuegen_jButton.setText("Grafik hinzufügen");
		hinzufuegen_jButton.addActionListener(new ActionListener()
		{

			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				
			}});
		
		return hinzufuegen_jButton;
	}
	
	/* Methode zum Linie zeichnen */
	private Graphics paintRect(Graphics2D g2)
	  {	
		 
		  for(int i=20; i<=21;i++)
		  {
			  g2.drawRect(50, 50, 100, 100);
		  }
		return g2;  
	  }
	
	/* diese Grafik soll bei Buttonpressed hinzugezeichnet werden */
	private Graphics paintFilledRect(Graphics2D g2)
	  {	
		 
		  for(int i=20; i<=21;i++)
		  {
			  g2.fillRect(50, 50, 100, 100);
		  }
		return g2;  
	  }
}
```


----------



## SlaterB (22. Aug 2008)

zu tun haben: keine Unterstriche in Variablen oder Methoden-Namen,
hinzufuegen_jButton
heißt
hinzufuegenJButton
oder
hinzufuegenButton

---------

ansonsten siehe Antwort von Marco13 für ein denkbares Konzept


----------



## cr3m4 (22. Aug 2008)

oh sorry Marco, hab deinen Beitrag voll übersehn 

danke für eure tatkräftige Unterstützung. Hoffe ich kriegs jetzt hin.


----------



## cr3m4 (25. Aug 2008)

guten morgen, ich habe nun Marcos beispiel mal versucht zu implementieren, was mir aber bedingt gelungen ist. irgendwas tut sich beim Buttonbetätigen, nur nicht was sein soll. Und zwar wird statt die vorgegebene Zeichnenmethode anzuwenden, ein Abbild des Buttons dargestellt, aber auch irgendwie nicht fest implementiert, da bei einem repaint die die Kopie des Buttonabbildes wieder verschwindet, but why?




Hier nochmal der komplette Sourcecode:


```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class PaintPanel extends javax.swing.JFrame {

	private static final long serialVersionUID = 1L;
	private PaintablePanel zeichenbereich_jPanel;
	private JButton hinzufuegen_jButton;
	private JPanel button_jPanel;
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				NewJFrame inst = new NewJFrame();
				inst.setLocationRelativeTo(null);
				inst.setVisible(true);
			}
		});
	}
	
	public PaintPanel() {
		super();
		initGUI();
	}
	
	
	interface Paintable
	{
	    void paintOn(Graphics g);
	}
	
	private void initGUI() {
		try {
			BorderLayout thisLayout = new BorderLayout();
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			getContentPane().setLayout(thisLayout);
			
			getContentPane().add(getZeichenbereich_jPanel(), BorderLayout.CENTER);
			getContentPane().add(getButton_jPanel(), BorderLayout.SOUTH);

			pack();
			setSize(400, 300);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	/* Zeichenbereich in dem alle Graphics-Objekte dargestellt werden */
	private JPanel getZeichenbereich_jPanel()
	{
		zeichenbereich_jPanel = new PaintablePanel()
		{
			private static final long serialVersionUID = 1L;

			public void paint( Graphics g ) 
			  { 
				  Graphics2D g2 = (Graphics2D)g;
				  super.paintComponents( g2 ); 
	
			  }
		  };
		return zeichenbereich_jPanel;
	};
	
	/* Container für Button */
	private JPanel getButton_jPanel()
	{
		button_jPanel = new JPanel();

		button_jPanel.add(getHinzufuegen_jButton());
		return button_jPanel;
	};
	
	/* Button mit der Actionmethode */
	private JButton getHinzufuegen_jButton()
	{
		hinzufuegen_jButton = new JButton();
		hinzufuegen_jButton.setText("Grafik hinzufügen");
		hinzufuegen_jButton.addActionListener(new ActionListener()
		{

			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				zeichenbereich_jPanel.addPaintable(new Lines()); 
			}});
		
		return hinzufuegen_jButton;
	}
	

	class Lines implements Paintable
	{
		
	    public void paintOn(Graphics g) { 
	    	setBackground(Color.BLACK);
	    	g.drawRect(10, 10, 50, 50); }
	}

	class PaintablePanel extends JPanel
	{
	    
		private static final long serialVersionUID = 1L;
		private List<Paintable> paintables = new ArrayList<Paintable>();

	    public void paintComponent(Graphics g)
	    {
	        super.paintComponent(g);
	        for (Paintable paintable : paintables)
	        {
	            paintable.paintOn(g);
	        }
	    }


	    void addPaintable(Paintable paintable)
	    {
	        paintables.add(paintable);
	        repaint();
	    }
	}
}
```


----------



## SlaterB (25. Aug 2008)

deine Klase heißt PaintPanel, toller Name für ein JFrame, in der main-Methode steht aber
NewJFrame inst = new NewJFrame();
??
außerdem heißt eine andere wichtige Klasse PaintablePanel,
dazu immer noch die Unterstriche in Variablen- und Methodennamen,
schrecklich, schrecklich, schrecklich

--------

das Problem ist/ sind Zeile 67-73,
dummerweise ist das super dort nicht PaintablePanel sondern das JFrame von NewJFrame/ PaintPanel,
deshalb wird der Button vom JFrame nochmal gezeichnet,

ich weiß im Moment gar nicht, wie du auf das richtige super, also PaintablePanel, zugreifen könntest in einer anonymen inneren Klasse,
hier aber auch gar nicht nötig, warum überschreibst du paint?
diese Methode ist so wie sie da steht ohne jeden Sinn, lasse sie weg und es funktioniert,


----------



## cr3m4 (25. Aug 2008)

boah super, funzt. Wegen der etwas unkonventionellen Formatierung und einigen ungereintheiten verzeih mir, habe bis vor 2 Monaten nix mit Java und wenig mit anderen Programmiersprachen am Hut gehabt. Ich gelobe Besserung 

so werd mich jetzt ran machen und die Methoden ins richtige Programm einbinden.

tnx ihr beiden.


----------

