# ArrayList<Line2D> mit g2d.draw() aufrufen



## Schaaaf (14. Feb 2012)

Hallo,

ich habe eine ArrayList entworfen:


```
public static ArrayList<Line2D> MyLines = new ArrayList<Line2D>();
```

Jetzt möchte ich aus dieser Liste jedes i-te Element grün färben und darstellen. Aber irgendwas haut nicht hin. Zumindestens sehe ich keinen Linie. :-(


```
public static Graphics2D g2d_high;
```


```
protected void paintComponent( Graphics g){
super.paintComponent(g);
g2d_high = (Graphics2D)g;
```


```
public static void getRelValues(Float RelVal, int RelValPos){
int step = 3;
for (int i = step; i < MyLines.size(); i=i+step){
g2d_high.setColor(Color.green);
g2d_high.drawLine(MyLines.get(i));
}
}
```


Was mache ich falsch?


----------



## Gast2 (14. Feb 2012)

So sollte man mit nem Graphics Objekt nicht umgehen. Es ist nicht garantiert, dass dein zwischengespeichertes Graphics Objekt noch gültig ist wenn deine getRelValues() Methode aufgerufen wird.

Wenn du zeichnest, dann mach das in der paintComponent() Methode.


----------



## Schaaaf (14. Feb 2012)

Okay...
Mein Problem hierbei ist, dass ich getRelValue() aufrufe, wenn ein Button gedrückt wurde. Dann schaue ich halt nach welcher gedrückt wurde und so und anschließend lege ich damit die "step" Variable fest. 

Wie kann ich das denn dann in die paintComponent() Methode einbauen, so dass es ja erst nach Button Klick ausgeführt/gemalt wird ?!


----------



## Gast2 (14. Feb 2012)

Wenn du den Button drückst veränderst du irgendwelche Werte und stößt dann per repaint() das neuzeichnen an. Die paintComponent() Methode schaut sich dann die Werte an und zeichnet dementsprechend.


----------



## Schaaaf (14. Feb 2012)

Gut, aber wo und wie rufe ich die repaint() Methode auf?


----------



## Gast2 (14. Feb 2012)

Wo? Direkt nachdem du deine Daten geändert hast.
Wie? deineComponentDieDuAktualisierenWillst.repaint();


----------



## Schaaaf (14. Feb 2012)

Aber wie gesagt, sieht meine paintComp so aus:


```
protected void paintComponent( Graphics g){
super.paintComponent(g);
...
```

Wenn ich die jetzt aufrufe, dann muss ich ja paintComponent(g) aufrufen, aber g ist ja nicht public, da es in paintComp definiert wird.

Komme da irgendwie durcheinander.


----------



## HimBromBeere (14. Feb 2012)

Um das Graphics-Objekt brauchst du dich nicht weiter kümmern, es ist einfach da und stellt genau den Bereich deines Bildschirmes dar, den du halt grade brauchst...


----------



## Schaaaf (14. Feb 2012)

Schreibe ich nur :


```
paintComponent().repaint();
```

kommt diese Meldung :

_The method paintComponent(Graphics) in the type Polygon is not applicable for the arguments ()_


----------



## Marco13 (14. Feb 2012)

???:L Die paintComponent ruft man nicht selbst auf, die wird automatisch aufgerufen, nachdem man irgendwo 'repaint()' aufgerufen hat. 

Sieh' dir mal Malen in Swing Teil 1: der grundlegende Mechanismus ? Byte-Welt Wiki an... und poste ggf. mal mehr Code, das zieht sich sonst ewig :noe:


----------



## Schaaaf (14. Feb 2012)

Wenn ich repaint() in meiner 


```
public static void getRelValues();
```

aufrufe, kommt dies.

_Cannot make a static reference to the non-static method repaint() from the type Component_

Ich weiß auch nicht was ich noch an Code posten sollte.


----------



## Gast2 (14. Feb 2012)

Wenn du nicht mehr Code posten kannst/willst, dann ließ dir das Tutorial durch, da werden all deine Fehler erklärt.


----------



## Schaaaf (14. Feb 2012)

Habe das Tutorial durch, aber bin noch keinen Schritt weiter. Was soll ich noch posten? Was ist denn noch relevant für euch? Könnte heulen...


----------



## Michael... (14. Feb 2012)

Grundsätzlich kann man nur sagen: Gezeichnet wird ausschließlich in der paintComponent. Ansonsten hilft: Grundlagen über Modifier und Zugriffsmöglichkeiten auf unterschiedlich deklarierte Variablen. Denken in Objekten...


----------



## poku17 (14. Feb 2012)

Ansich ist ja jetzt dein prob, dass du repaint() nicht aus statischem Kontext aufrufen kannst... wuesste auch nicht wie das gehen sollte... aber wenn du den Rest auch nicht statisch machst, wuerdest du sie aufrufen koennen... hatte das prob vorhin auch selber, habe dan alles non-static gemacht...

Und es ist immer gut, möglichst viel Quellcode zu posten, dann kann man auch gleich Tips geben wie du es ummodelieren koenntest und etc....


----------



## GUI-Programmer (14. Feb 2012)

Kann allen meinen Vorredner zustimmten.

Hier eine mögliche Lösung:

```
// actionPerformed deines Buttons:
public void actionPerformed(ActionEvent evt) {
	/*
	 * drawingArea ist eine Instanz deiner Zeichenklasse, d.h. welche
	 * bei AWT von Panel oder Canvas und bei Swing von JPanel oder
	 * JComponent erbt. Evtl auch die Klasse selbst -> in diesem Fall
	 * anstatt von drawingArea.repaint(); dann this.repaint() aufrufen.
	 */
	drawingArea.repaint();
}

// deine Zeichenmethode, die paintComponent():
protected void paintComponent(Graphics g) {
	super.paintComponent(g);
	Graphics2D g2 = (Graphics2D) g;
	for(int i = 3; i<MyLines.size(); i+=3) {
		g2.setColor(Color.GREEN);
		g2.drawLine(MyLines.get(i));
	}
}
```

Dennoch solltest du dir unbedingt das Zeichnen in Swing Tutorial anschauen und verstehen. Evtl. hilft auch das KEIN Swing-Tutorial.


----------



## Schaaaf (14. Feb 2012)

Da der Button in einer anderen Klasse ist, kann ich bei dem Aufruf nicht das static weglassen. Ich werde mir die Nacht noch den Kopf zerbrechen... Vlt. verstehe ich ja noch, was ich machen muss.


----------



## Michael... (14. Feb 2012)

Schaaaf hat gesagt.:


> Da der Button in einer anderen Klasse ist, kann ich bei dem Aufruf nicht das static weglassen.


Falscher Ansatz. Wie gesagt in Objekten denken und mit Objekten arbeiten. In Deinem Fall sollte das einzige static das static der main Methode sein.


----------



## GUI-Programmer (14. Feb 2012)

... Genau. Daher Getter und Setter und evtl. nötige Objekte im Konstrukor übergeben. Oder von anfang an nach MVC programmieren --> Signatur.


----------



## poku17 (14. Feb 2012)

Du kannt der Klasse, die den Button enthaelt, get/set methoden geben, sprich den Button kapseln oder du machst den Button public und und sprichst ihn direkt an MeineKlasse.ButtonName, was die unschönere variante waere, wie ich finde ^^

[Java]
public JButton getButton(){
  return deinButton;
}

public void setButton(JButton btn){
  deinButton = btn;
}
[/Java]

aber alles statisch machen ist nicht schön... ^^


----------



## Marco13 (15. Feb 2012)

Hmja, sinngemäß: So, wie du bisher das Graphics weitergereicht hast, kannst du auch die Zeichen-Component weiterreichen. Aber mit dem static ist das halt in jedem Fall häßlich. Poste am besten einfach mal mehr Code, ein KSKB ist immer am besten.


----------



## Schaaaf (15. Feb 2012)

Okay, danke für eure Mühen. Ich bastel jetzt erstmal meinen gesamten Code so um, dass static verschwindet und dann sortiere ich alles aus der paintComponent() Methode raus, was da nix zu suchen hat. Vlt. geht auch mir dabei ein Licht auf...Ich hoffe es.


----------



## Schaaaf (15. Feb 2012)

So, das ist mein neuer Code:

1. Alles aus der paintComp rausgeworfen, was da nix zu suchen hat:


```
public class PaintingClass extends JComponent
{
    private ArrayList<Shape> shapes = new ArrayList<Shape>();
    private ArrayList<JLabel> labels = new ArrayList<JLabel>();
    private ArrayList<Shape> lines = new ArrayList<Shape>();
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        System.out.println("s: "+shapes.size()+"   l: "+lines.size()+"   lab: "+labels.size());
        if(shapes.size() != 0 ){
        	for (Shape s : shapes ) {
        		g2d.draw(s);
        	}
        } 
        
        if(lines.size() != 0 ){
        	for (Shape line : lines ) {
        		g2d.draw(line);
        	}
        }
        
        if (labels.size() != 0){
        	for (JLabel l : labels) {
        		this.add(l);
        	}
        }
    }
    
    public void setAllShapes(ArrayList<Shape> shapes) {
    	this.shapes = shapes;
    }
    
    public void setAllLines(ArrayList<Shape> lines) {
    	this.lines = lines;
    }
    
    public void setAllLabel(ArrayList<JLabel> labels) {
    	this.labels = labels;
    }
}
```

2. alles statische gelöscht. nur noch die Main ist static.

3. Die Button Methode :


```
private Polygon polygon = new Polygon ();

private JButton neuMalen() {
		if (showBtn == null) {
			showBtn = new JButton("Neu malen");
			showBtn.setMaximumSize(new Dimension(150, 2));
			showBtn.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					polygon.getRelValues();	
				}
			});
		}
		return showBtn;
	}
```

4. aufgerufene Klasse polygon.getRelValues()


```
public void getRelValues(Float RelVal, int RelValPos){
		
lines.clear();
		
Shape line = new Line2D.Float(120,120,200,200);
lines.add(line);

paintingComponent.setAllLines(lines);
paintingComponent.setAllShapes(shapes);
paintingComponent.repaint();
}
```

Jetzt sollte doch alles funktionieren, d.h. alle bisher gezeichnete Lines weg und nur die neue Linie malen.... dachte ich... aber geht wieder nicht. Was mache ich denn noch falsch?


----------



## Gast2 (15. Feb 2012)

Poste nen KSKB.


----------



## Schaaaf (15. Feb 2012)

ich weiß zwar nicht genau wie man ein KSKB macht, aber hier mal der Code (sind 4 Klassen)


```
import java.awt.BorderLayout;

import javax.swing.JFrame;

	@SuppressWarnings("serial")
	public class ParallelCoordClass extends JFrame {
		
		public static void main(String[] args) {

			ParallelCoordClass pc = new ParallelCoordClass(); 
	        pc.setTitle("Mein Prog");    
   
	        Properties prop = new Properties();	        
	        pc.add(prop, BorderLayout.EAST);
	        
	        Polygon polygon = new Polygon();
	        pc.add(polygon, BorderLayout.WEST);

	        pc.setSize(1024,700); 
	        pc.setDefaultCloseOperation(EXIT_ON_CLOSE);
	        pc.setVisible(true);	
  
	   }			
	}
```


```
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JPanel;

public class Polygon extends JPanel{
	
	private PaintingClass paintingComponent = new PaintingClass();
	private ArrayList<Shape> lines = new ArrayList<Shape>();
	
	public Polygon() {
		super();	
		initialize();
		createPaintComp();
	}
	
	private void initialize() {		
		this.setBorder(BorderFactory.createTitledBorder(null, "Many-to-Many Relational Parallel Coordinates Dispaly"));
		paintingComponent.setPreferredSize(new Dimension(760,450));
		this.add(paintingComponent,BorderLayout.CENTER);
		this.setVisible(true);
	}
	
	private void createPaintComp() {
        
		Shape line = new Line2D.Float(150,150,300,300);
		lines.add(line);
		 
		paintingComponent.setAllLines(lines);
		paintingComponent.repaint();
	}
	
	public void getRelValues(){
        
		lines.clear();
		        
		Shape line = new Line2D.Float(120,120,200,200);
		lines.add(line);
		 
		paintingComponent.setAllLines(lines);
		paintingComponent.repaint();
		}	
}
```


```
import java.awt.BorderLayout;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.TitledBorder;

@SuppressWarnings("serial")
public class Properties extends JPanel{
	
	private Polygon polygon = new Polygon ();
	private PaintingClass paintingComponent = new PaintingClass();
	
	private JPanel VarNamesPanel = null;
	private JPanel PropPanel = null;
	private ButtonGroup ButtonGroup = null;
	private JRadioButton NameBtn = null;
	public String CurrentVar = "...";
	public String[] splitNames;
	private Choice choice;
	private String values;
	private JButton showBtn;
	
	public static float RelValue;
	public static int RelValPos;

	public Properties() {
		super();
		initialize();
		this.add(getVarNamesPanel(), null);			
	}	
	
	private void initialize() {
		this.setBorder(BorderFactory.createTitledBorder(null, "Properties"));
		this.setPreferredSize( new java.awt.Dimension(250, 410));	
	}
	
	private JPanel getVarNamesPanel() {
		if (VarNamesPanel == null) {
			VarNamesPanel = new JPanel();
			VarNamesPanel.setPreferredSize( new java.awt.Dimension(230, 200));
			VarNamesPanel.setBorder(BorderFactory.createTitledBorder(null, "Names of Variables", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, new Font("Dialog", Font.BOLD, 12), new Color(51, 51, 51)));
			VarNamesPanel.setLayout(new BoxLayout(getVarNamesPanel(), BoxLayout.Y_AXIS));
			VarNamesPanel.add(showChoice(), BorderLayout.NORTH);
			VarNamesPanel.add(Box.createHorizontalGlue());
		}
		return VarNamesPanel;
	}

	private JButton showChoice() {
		if (showBtn == null) {
			showBtn = new JButton("Show Choice");
			showBtn.setMaximumSize(new Dimension(100, 50));
			showBtn.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					polygon.getRelValues();	
				}
			});
		}
		return showBtn;
	}	    
}
```


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.util.ArrayList;

import javax.swing.JComponent;

public class PaintingClass extends JComponent
{
    private ArrayList<Shape> lines = new ArrayList<Shape>();
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        
        if(lines.size() != 0 ){
        	g2d.setColor(Color.red);
        	for (Shape line : lines ) {
        		g2d.draw(line);
        	}
        }
    }

    public void setAllLines(ArrayList<Shape> lines) {
    	this.lines = lines;
    }
}
```

Das kann man ausführe und es reagiert genauso wenig, wie das gesamte Programm auf repaint()


----------



## Gast2 (15. Feb 2012)

Hm, da weiß man gar nicht wo man anfangen soll 

Erstmal zu deinem Fehler:
Zu erzeugst zwei unterschiedliche Instanzen von Polygon, davon wird aber nur eine bei dir angezeigt. Die Änderungen machst du aber der die nicht angezeigt wird.

Und noch nen paar Hinweise:

```
public class ParallelCoordClass extends JFrame {
```
Brauchst du nicht, es reicht wenn du in der Klasse nen JFrame erzeugst.

Properties und Polygon: Benenn nie Klasse so wie Klassen aus der Java API. Das stiftet nur verwirrung.


```
private final PaintingClass paintingComponent = new PaintingClass();
```
Davon erzeugst du auch zwei unterschiedliche Instanzen. Brauchst du nicht.


```
private Choice choice;
```
Hier mischst du AWT und Swing Komponenten, sollte man nicht machen.

Ob Properties und Polygon JPanel erweitern müssen ist auch fraglich.


----------



## Schaaaf (15. Feb 2012)

> Zu erzeugst zwei unterschiedliche Instanzen von Polygon, davon wird aber nur eine bei dir angezeigt. Die Änderungen machst du aber in der, die nicht angezeigt wird.



Und wie kriege ich das gelöst? Ich kann ja nicht einfach eine löschen und static "darf" ich ja nicht.

Danke für die anderen Hinweise.


----------



## Gast2 (15. Feb 2012)

Erzeuge einfach nur eine Instanz und gib die weiter.


----------

