# Variablen an anonyme Funktion



## ocean.driver (15. Feb 2011)

Hallo,

Ich habe ein Fenster entwickelt, welches ein zwei Parameter hat: Ein Abstraktes Tabellenmodell und einen rowIndex. 

Das Fenster generiert automatisch eine Oberfläche für das gegebene Tabellenmodell um Datensätze hinzuzufügen oder zu editieren.

Jetzt ist mein Tabellenmodell wie folgt erweitert:

Es steht eine Methode zur Verfügung die für bestimmte Spalten eine ArrayList von gültigen Werten zurückgibt (sonst null). 
Zusätlich reagiere ich unterschiedlich, je nach dem ob ein Attribut mehrere Werte aufnehmen kann oder nur eines.

Für den Fall einer Einzelauswahl wird eine ComboBox generiert.

Jetzt kommen wir dem wichtigen Punkt, dass ein Feld beliebig viele Werte annehmen kann und nur bestimmte werte angenommen werden können.
Für diesen Fall hab ich ein weiteres Fenster entworfen. Dort sind zwei JList drauf zwischen denen die Werte übergeben werden.
Jetzt habe ich meinem Fenster zwei Variablen:
 - ausgewählte Werte
 - nicht ausgewählte Werte

Da dies aber für mehrere Werte sein kann, tauchen öfters die anonymen Funktion auf. Aber wie krieg ich die Variablen vernünftig hin?
Ich hab hier die wichtigen Codeausschnitte einmal zusammengestellt:



```
public DataModificationWindow(final AbstractMediaTableModel atm, int rowIndex)
	{
		double[] cols = {80,100,80,100};
		double[] rows = new double[(int) Math.ceil((double)atm.getColumnCount() / 2)+1];
		for(int i=0; i < rows.length; i++)
			rows[i] = 25;		
		
		double size[][] = {cols,rows};

		TableLayout tl = new TableLayout(size);
		panel = new JPanel(tl);
		
		boolean isOdd = (atm.getColumnCount() % 2) == 1;
		
		final ArrayList<Object[]> col_sources = new ArrayList<Object[]>();
		
		for(int i=0; i < atm.getColumnCount(); i++)
			col_sources.add(atm.getColumnKeys(i));
		
		
		final ArrayList<String> not_selected_vals = new ArrayList<String>();
		final ArrayList<String> selected_vals = new ArrayList<String>();

		
		for(int i=0; i < atm.getColumnCount(); i=i+2)
		{
			/*
			 * Der Ausdruck:
			 * 	(isOdd && (atm.getColumnCount()-i) == 1 ? 2:4)
			 * liefert im Falle des letzten Elementes eine 2 zurück, sonst 4 
			 */
			for(int j=0   ;   j < (isOdd && (atm.getColumnCount()-i) == 1 ? 2:4)  ;   j=j+2)
			{		
				....
				....
				....
				
						temp.addMouseListener(new MouseAdapter() {
													
							@Override
							public void mouseClicked(MouseEvent e) {

								new ListSelector(not_selected_vals, selected_vals);
							}
						});
						
						panel.add(temp, datafield_pos);
					
					}
					else
					{
						System.out.println("Value is no ArrayList");
						panel.add(new JComboBox(col_sources.get(i+(j/2))),datafield_pos);						
					}
				}


					
			}
		}
				....
				....
				....
		
	}
```

Danke schoneinmal für die Hilfe


----------



## Marco13 (16. Feb 2011)

Etwas weniger text und etwas weniger Code, dafür _spezifischer_... Meinst du sowas wie


```
int someValue = 123;

something.addSomeListener(new Listener()
{
    void somethingHappened(Event event)
    {
        System.out.println("Value: "+someValue); // GEHT NICHT!
    }
});
```
? 

Falls ja:

```
int someValue = 123;
final int someFinalValue = someValue;
something.addSomeListener(new Listener()
{
    void somethingHappened(Event event)
    {
        System.out.println("Value: "+someFinalValue); // GEHT
    }
});
```


----------



## ocean.driver (16. Feb 2011)

finalisieren geht nicht, da ich ja über alle Spalten des Tabellenmodells iteriere und so der Wert quasi jede Runde nen anderen Wert erhält.


----------



## Marco13 (16. Feb 2011)

Poste ein zusammenhängendes Codestück, beginnend bei der Deklaration der Variablen, über die Zuweisung, bis zu der Stelle, wo das Problem ist

```
int variable; // <- diese Variable

...

variable = 123;

...


doSomething(variable); // <- soll  hier verwendet werden
```

Aber ohne "..." dazwischen. Vielleicht hilft das.


----------



## ocean.driver (20. Feb 2011)

Hi,

Hier der komplette Code


```
public DataModificationWindow(final AbstractMediaTableModel atm, int rowIndex)
	{
		double[] cols = {80,100,80,100};
		double[] rows = new double[(int) Math.ceil((double)atm.getColumnCount() / 2)+1];
		for(int i=0; i < rows.length; i++)
			rows[i] = 25;		
		
		double size[][] = {cols,rows};

		TableLayout tl = new TableLayout(size);
		panel = new JPanel(tl);
		
		boolean isOdd = (atm.getColumnCount() % 2) == 1;
		
		final ArrayList<Object[]> col_sources = new ArrayList<Object[]>();
		
		for(int i=0; i < atm.getColumnCount(); i++)
			col_sources.add(atm.getColumnKeys(i));
		
		
		final ArrayList<String> not_selected_vals = new ArrayList<String>();
		final ArrayList<String> selected_vals = new ArrayList<String>();

		
		for(int i=0; i < atm.getColumnCount(); i=i+2)
		{
			/*
			 * Der Ausdruck:
			 * 	(isOdd && (atm.getColumnCount()-i) == 1 ? 2:4)
			 * liefert im Falle des letzten Elementes eine 2 zurück, sonst 4 
			 */
			for(int j=0   ;   j < (isOdd && (atm.getColumnCount()-i) == 1 ? 2:4)  ;   j=j+2)
			{		
				panel.add(new JLabel(atm.getColumnName(i+(j/2)) + ": "),j+"," + (i/2)+",r" );
				
				System.out.println("i+(j/2) = " + Integer.valueOf(i+(j/2)));
				final Object[] col_source = atm.getColumnKeys(i+(j/2));
								
				
				String datafield_pos = (j+1)+","+(i/2);
				
				if(col_source == null)
				{
					System.out.println("col_source == null");
					panel.add(new JTextField (""),datafield_pos);	
				}
				else
				{
					if (atm.getValueAt(0, i+(j/2)) instanceof ArrayList)
					{
						System.out.println("Value is ArrayList");
						JButton temp = new JButton("Verwalten");
						
						not_selected_vals.clear();
						selected_vals.clear();						

						ArrayList<String> temp_selected_vals = (ArrayList<String>) atm.getValueAt(rowIndex, i+(j/2));

						System.out.println("i+(j/2) = " + (i+j/2));
						

						for(int k=0; k < col_source.length; k++)
							not_selected_vals.add(atm.getColumnKeyValue(i+(j/2), (String)col_source[k]));

						for(int k=0; k < temp_selected_vals.size(); k++)
							selected_vals.add(atm.getColumnKeyValue(i+(j/2),(String)temp_selected_vals.get(k)));



						//not_selected_vals = not_selected_vals - selected_vals
						for(int k=0; k < not_selected_vals.size(); k++)
							if(selected_vals.contains(not_selected_vals.get(k)))
								not_selected_vals.set(k, null);
						
						while(not_selected_vals.remove(null));
						
						
						System.out.println("notSelected");
						for(String s: not_selected_vals)
							System.out.println("\t"+s);
						
						System.out.println("selected");
						for(String s: selected_vals)
							System.out.println("\t"+s);

						
						
						temp.addMouseListener(new MouseAdapter() {
													
							@Override
							public void mouseClicked(MouseEvent e) {

								
								
								new ListSelector(not_selected_vals, selected_vals);
							}
						});
						
						panel.add(temp, datafield_pos);
					
					}
					else
					{
						System.out.println("Value is no ArrayList");
						panel.add(new JComboBox(col_sources.get(i+(j/2))),datafield_pos);						
					}
				}


					
			}
		}
		
		if(rowIndex == AbstractMediaTableModel.CREATE_NEW)
		{
			atm.setValueAt("", (int)rowIndex, 0);
			rowIndex = atm.getRowCount()-1;
		}
		else
		{
			Component comp;
	    	for(int i=1; i < panel.getComponents().length; i=i+2)    /* 1,3,5,7,9,11,... */
	    	{
	    		comp = panel.getComponent(i);
	    		
	    		if(comp instanceof JTextField)
	    			((JTextField)comp).setText((String) atm.getValueAt((int)rowIndex, (int)i/2).toString());
	    		
	    		else if(comp instanceof JComboBox)
	    			((JComboBox)comp).setSelectedItem(atm.getValueAt((int)rowIndex, (int)i/2));
	    		
	    	}
		}


		JButton jb_save = new JButton("speichern");
		
		jb_save.addMouseListener(new MouseAdapter(){
			
			
			//muss geändert werden
		    public void mouseClicked(MouseEvent e) 
		    {
		    	Component comp;
		    	String text="";
		    	for(int i=1; i < panel.getComponents().length; i=i+2)    /* 1,3,5,7,9,11,... */
		    	{														 
		    		comp = panel.getComponent(i);
		    		
		    		if(comp instanceof JTextField)
		    			text = ((JTextField)comp).getText();
		    		
		    		else if(comp instanceof JComboBox)
		    			text = ((JComboBox)comp).getSelectedItem().toString();
		    		
		    		atm.setValueAt(text, 0, (int)i/2);
		    	}
		    	atm.fireTableDataChanged();
		    	
		    	setVisible(false);
		    	dispose();		    	
		    }
		});
		
		if(isOdd) 
			panel.add(jb_save,"1,"+ ((int)(atm.getColumnCount()/2)+1+",c,c")); /* ungerade Spaltenanzahl */
		else
			panel.add(jb_save,"1,"+ ((int)(atm.getColumnCount()/2)+",c,c")); /* gerade Spaltenanzahl */

		getContentPane().add(panel);


		setTitle("Eintrag bearbeiten / hinzufügen");
		setResizable(true);
		setVisible(true);
		pack();
	}
```


----------



## Marco13 (20. Feb 2011)

Und was soll dort wo wo hin übergeben werden?


----------



## ocean.driver (20. Feb 2011)

An Zeile 105 sollen die beiden Listen übergeben werden, die aber prinzipiell nicht final sein dürfen.

Es geht mir hier auch garnicht um eine konkrete Lösung, sondern um den allgemeinen Weg wie sowas zu realisieren ist.


----------



## Marco13 (20. Feb 2011)

Ach, die beiden Listen...
[c]panel.add(new JComboBox(col_sources.get(i+(j/2))),datafield_pos);[/c]
?
(Bin ich der einzige, der nicht kapiert, wo hier die Frage ist? ???:L )
*seufz*

_finalisieren geht nicht, da ich ja über alle Spalten des Tabellenmodells iteriere und so der Wert quasi jede Runde nen anderen Wert erhält. _
Das ändert ja nichts daran, dass man etwas finales an die inneren Klassen übergeben kann... Hilft vielleicht das

```
for (int notFinalValue=0; notFinalValue<10; notFinalValue++)
{
    final int finalValue = notFinalValue;
    something.addSomeListener(new Listener()
    {
        void somethingHappened(Event event)
        {
            System.out.println("Value: "+finalValue); // GEHT
        }
    });
}
```

?!?


----------



## ocean.driver (20. Feb 2011)

Hi,

ALso not_selected_vals und selected_vals sind gemeint. Ja aber wie soll ich etwas als final an die Methode übergeben, was sich jede Runde ändert?
Ich kann ja nicht in der nächsten iteration einen finalen Wert überschreiben,oder?


----------



## Marco13 (21. Feb 2011)

Also... was du da genau mit diesen beiden Listen machst..

```
// holen ?!
ArrayList<String> temp_selected_vals = (ArrayList<String>) atm.getValueAt(rowIndex, i+(j/2));
// ... äh füllen
for(int k=0; k < temp_selected_vals.size(); k++)
    selected_vals.add(atm.getColumnKeyValue(i+(j/2),(String)temp_selected_vals.get(k)));
// wtf?!
while(not_selected_vals.remove(null));
```
.... ist egal: Kurz bevor du die Anonyme Klasse erstellst, solltest du 


```
[b]final[/b] List<String> finalInstanceOfWhatever = new ArrayList<String>(theThingThatChangesInEachIteration);
```
machen können, und DIE dann in der inneren Klasse verwenden können.


----------



## Antoras (21. Feb 2011)

Dein Code, der ist so kaputt, den bekommst du wahrscheinlich nie zum laufen.

Bau da mal ein vernünftiges Konzept ein, damit ein Außenstehender erkennen kann was der Code überhaupt machen soll. Zusammenhängende Codeteile gehören in eine eigne Methode. Jeglicher Code, der nicht direkt bei der Initialisierung eines Objektes beteiligt ist, hat nichts im Konstruktor verloren (was bei dir so ziemlich alles wäre).
Dein Code in den anonymen Klassen hat da auch nichts verloren. Wenn du aus den Listenern heraus einfach nur eine Methode des Objektes aufrufst brauchst du auch keine finalen Variablen mehr. Z.B.:

```
@Override
public void mouseClicked(MouseEvent e) {
  handleMouseClick();
}
```

Das bisschen Refactoring muss einfach sein, sonst wird das nichts.


----------

