# Auf gefüllte ArrayList zugreifen



## PhilBauing (1. Jul 2012)

Guten Morgen,

ich habe in meiner GUI mehrere JTable, welche ich über ActionListener mit Daten aus ArrayListen fülle. Bei einem Table habe ich es ganz gut hinbekomme:



```
package rohrnetz;

import java.util.ArrayList;

import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

public class SchaechteTableModel implements TableModel {
	ArrayList<Schacht> schaechte= new ArrayList<Schacht>();
	private ArrayList<TableModelListener> listeners = new ArrayList<TableModelListener>();

	// Ich muss ehrlich gestehen, dass ich diese Methode nur halb verstehe, sie ist glaube ich dazu dazu da, einen Schacht zum Table hinzuzufügen
	public void addSchacht(Schacht schacht) {
		int index = schaechte.size();
		schaechte.add(schacht);

// Hier werden glaube ich die listener benachrichtigt, wenn sich was im Table ändert. Ich habe es so verstanden, dass das TableModelEvent ist, wenn dem Table Zeilen //eines bestimmten Indeces zugefügt werden. 
		TableModelEvent e = new TableModelEvent(this, index, index,
				TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT);
// ich glaub hier werden die listeners benachrichtigt, weiß aber nicht wer diese für das TableModelEvent sind
		for (int i = 0, n = listeners.size(); i < n; i++) {
			((TableModelListener) listeners.get(i)).tableChanged(e);
		}
	}
// Die Anzahl der Zeilen ist immer so groß wie die größe der ArrayList schaechte
        public int getRowCount() {
		return schaechte.size();
	}
         public int getColumnCount() {
		return 4;
	}
//Benennt die Spalten
	public String getColumnName(int columnIndex) {
		switch (columnIndex) {
		case 0:
			return "Nr.";
		case 1:
			return "Tiefe";
		case 2:
			return "Durchmesser";
		case 3:
			return "Volumenstrom";
		default:
			return null;
		}
	}
//gibt den Spalten Typen
	public Class<?> getColumnClass(int columnIndex)
	
	{
		switch (columnIndex)
		{
		case 0:
			return Integer.class;
		case 1:
			return Double.class;
		case 2:
			return Double.class;
		case 3:
			return Double.class;
		default:
			return null;
		}
	}
	//Table ist nicht editierbar
	public boolean isCellEditable (int rowIndex, int columnIndex)
	{
		return false;
	}
	
	public Object getValueAt(int rowIndex,int columnIndex)
	{
		Schacht schacht =  schaechte.get(rowIndex);
		switch (columnIndex)
		{
		case 0:
			return rowIndex+1;  //1. Spalte nummerierung
		case 1:
			return schacht.getTiefe(); //2. Spalte Tiefe des jeweiligen Schachtes. Getter der Klasse Schacht
		case 2:
			return schacht.getDurchmesser(); //3. Der Durchmesser. Getter der Klasse Schacht
			
		case 3:
			return schacht.getZulaufmenge(); //3. Zulaufmenge. Getter der Klasse Schacht
		default:
			return null;
	}
}
	
	public void addTableModelListener(TableModelListener l)
	{
		listeners.add(l);
	}
	public void removeTableModelListener(TableModelListener l)
	{
		listeners.remove(l);
	}
}
```

Und das zweite TableModel:


```
//Ich habe versucht es so zu machen wie beim ersten Table.
public class HaltungenTableModel implements TableModel {
	ArrayList<Haltung> haltungen = new ArrayList<Haltung>();
	ArrayList<Schacht> schaechte;  //hier habe ich nicht new ArrayList verwendet, weil ich ja //die bereits existierende verwenden möchte. Beides hilft nicht
	private ArrayList<TableModelListener> listeners = new ArrayList<TableModelListener>();

	public void addHaltung(Haltung haltung) {
		int index = haltungen.size();
		haltungen.add(haltung);
		
		TableModelEvent e = new TableModelEvent(this, index, index,
				TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT);
		for (int i = 0, n = listeners.size(); i < n; i++) {
			((TableModelListener) listeners.get(i)).tableChanged(e);
		}
	}
// alles ähnlich wie beim anderen tabel
public int getRowCount() {
		return haltungen.size();
	}

	public int getColumnCount() {
		return 4;
	}
// Die Namen
	public String getColumnName(int columnIndex) {
		switch (columnIndex) {
		case 0:
			return "Anfangsschacht";
		case 1:
			return "Endschacht";
		case 2:
			return "Gefälle";
		case 3:
			return "Durchmesser";
		default:
			return null;
		}
	}
// Die Typen
	public Class<?> getColumnClass(int columnIndex)

	{
		switch (columnIndex) {
		case 0:
			return Integer.class;
		case 1:
			return Integer.class;
		case 2:
			return Double.class;
		case 3:
			return Double.class;
		default:
			return null;
		}
	}

	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return false;
	}
// Hier liegt der unterschied und das Problem. Ich möchte in der 3. Spalte eine Methode //aufrufen, welche sowohl auf schaechte, als auch auf haltungen zugreift. Die Methode habe ich //in
// einer Klasse Berechnungsklasse geschrieben
	public Object getValueAt(int rowIndex, int columnIndex) {

		Haltung haltung = haltungen.get(rowIndex);
		
		
		switch (columnIndex) {
		case 0:
			return haltung.getAnfangschacht() + 1;
		case 1:
			return haltung.getEndschacht() + 1;
		case 2:
//Hier ist immer der verweis auf eine NullPointerException oder auf //java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 
// Ich glaube, dass das daran liegt, dass diese Klasse nicht die gefüllte ArrayList schaechte 
// kennt
			return Berechnungsklasse.berechneGefaelle(haltungen, schaechte, rowIndex); 
		case 3:
			return haltung.getDurchmesser();
		default:
			return null;
		}
	}

	public void addTableModelListener(TableModelListener l) {
		listeners.add(l);
	}

	public void removeTableModelListener(TableModelListener l) {
		listeners.remove(l);
	}

}
```

Hier auszüge aus meiner Klasse Benutzeroberfläche:

[Java]


	public Benutzeroberflaeche() throws InterruptedException {


final Rohrnetz rohrnetz = new Rohrnetz(); 


		final SchaechteTableModel model = new SchaechteTableModel(); //neues SchaechteTableModel
	        final HaltungenTableModel model2 = new HaltungenTableModel(); //neuesHaltungenTableModel


		[...]
//table ist im scrollPane, das verwendete model ist SchaechteTableModel, das ist der "funktionierende" Table
		final JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(10, 175, 335, 100);
		panel.add(scrollPane);
		table = new JTable(model);
		scrollPane.setViewportView(table);


                JScrollPane scrollPane_1 = new JScrollPane();
		scrollPane_1.setEnabled(false);                      //wird auf true gesetzt, durch eine Methode im aktionListener, funktioniert, hier liegt nicht das Problem, ich habe die Methode ausgelassen. 
		scrollPane_1.setBounds(10, 145, 335, 100);
		panel_1.add(scrollPane_1);
		table_1 = new JTable(model2); //hier wird model2 verwendet
		table_1.setEnabled(false);
		scrollPane_1.setViewportView(table_1);

		[...]
		[...]
		[...]

                JButton btnNewButton_1 = new JButton("Schacht erzeugen");
		btnNewButton_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				schachthinzufuegen();
				model.addSchacht(rohrnetz.getSchaechte().get(model.getRowCount()));

                                private void schachthinzufuegen() {

					double xKoordinate;
					double yKoordinate;
					double zKoordinate;
					double tiefe;
					double durchmesser;
					double volumenstrom;

//Hier wird sich auf den Inhalt von Textfeldern auf der Benutzeroberläche bezogen.
					xKoordinate = Double.parseDouble(textField.getText());
					yKoordinate = Double.parseDouble(textField_1.getText());
					zKoordinate = Double.parseDouble(textField_2.getText());
					tiefe = Double.parseDouble(textField_3.getText());
					durchmesser = Double.parseDouble(textField_4.getText());
					volumenstrom = Double.parseDouble(textField_5.getText());

					Schacht neuerSchacht = new Schacht(0, 0, 0, 0, 0, 0);
					neuerSchacht.setxKoordinate(xKoordinate);
					neuerSchacht.setyKoordinate(yKoordinate);
					neuerSchacht.setzKoordinate(zKoordinate);
					neuerSchacht.setTiefe(tiefe);
					neuerSchacht.setDurchmesser(durchmesser);
					neuerSchacht.setZulaufmenge(volumenstrom);

//Beim betätigen des Buttons, wird ein neues Objekt der ArrayList schaechte zugefügt.

					rohrnetz.getSchaechte().add(neuerSchacht);


			}
		});


	[...]

		JButton btnHaltungErzeugen = new JButton("Haltung erzeugen");
		btnHaltungErzeugen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				haltungerzeugen();
				model2.addHaltung(rohrnetz.getHaltungen().get(model2.getRowCount()));


			}

                private void haltungerzeugen() {

//hier wird wie bei dem anderen Aktionlistener die ArrayList haltungen mit Objekten gefüllt. Haltung (int anfangsschacht, in endschacht, double durchmesser){
//die Daten werden mit Comboboxen übergeben. Ich habe mit System.out.print() überprüft, ob der ArrayList neue Objekte zugefügt werden und dem ist auch so. 

		int anfangsschacht;
                int endschacht;
                double durchmesser;

                endschacht = endcombobox.getSelectedIndex();
                anfangsschacht = anfangscombobox.getSelectedIndex();
                durchmesser = Double.parseDouble(textField_6.getText());

                if (anfangsschacht==endschacht) 
                {
                    JOptionPane.showMessageDialog(null, "Endschacht kann nicht gleich dem Anfangsschacht sein!");
                }
                else    
                {


                    Haltung neueHaltung = new Haltung(0,0,0);
                    neueHaltung.setAnfangsschacht(anfangsschacht);
                    neueHaltung.setEndschacht(endschacht);
                    neueHaltung.setDurchmesser(durchmesser);

                    rohrnetz.getHaltungen().add(neueHaltung);


			}
		}});
		btnHaltungErzeugen.setEnabled(false);
		btnHaltungErzeugen.setBounds(10, 371, 158, 23);
		panel_1.add(btnHaltungErzeugen);
	}
public static void main(String[] args) {




		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Benutzeroberflaeche frame = new Benutzeroberflaeche();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

}
[/Java]

Die Berechnungsklasse:

[Java]

public class Berechnungsklasse {

	}

	public static double berechneGefaelle(ArrayList<Haltung> haltungen,ArrayList<Schacht> schaechte, int nummer){
		Haltung haltung =haltungen.get(nummer);
		int anfangsnummer = haltung.getAnfangschacht();
		int endnummer = haltung.getEndschacht();
		Schacht anfangsschacht = Rohrnetz.getSchaechte().get(anfangsnummer); // Hier ist 
//Der zweite verweis auf die leereListe, wenn ich den Button betätige. Ich schließe aus, dass es 
//an den Indices liegt. Ich habe sehr sehr viel rumprobiert und ich bekomme selbst bei einer 
//IndexOutOfBoundsException die size nicht größer als 0. 

		Schacht endschacht = schaechte.get(endnummer);
		double anfangs_tiefe = anfangsschacht.getTiefe();
		double end_tiefe = endschacht.getTiefe();
		double anfangs_X_koordinate = anfangsschacht.getxKoordinate();
		double end_X_koordinate = endschacht.getxKoordinate();
		double anfangs_Y_koordinate = anfangsschacht.getyKoordinate();
		double end_Y_koodinate = endschacht.getyKoordinate();
		double anfangs_Z_koordinate = anfangsschacht.getzKoordinate();
		double end_Z_koordinate = endschacht.getzKoordinate();
		double X_differenz = anfangs_X_koordinate - end_X_koordinate;
		double Y_differenz = anfangs_Y_koordinate - end_Y_koodinate;
		double Z_differenz = anfangs_Z_koordinate - anfangs_tiefe
				- (end_Z_koordinate - end_tiefe);
		double absolutZ_differenz = Math.abs(Z_differenz);
		double distanz = Math.sqrt(Math.pow(X_differenz, 2)
				+ Math.pow(Y_differenz, 2) + Math.pow(Z_differenz, 2));

		double gefaelle = (absolutZ_differenz / distanz) * 100;

		return gefaelle;
	}




}[/code]

Das ergebnis einer Methode in einem case wiederzugeben funktioniert für mein SchaechteTableModel, wenn ich in der Methode nur auf schaechte zugreife, z.B.
[Java]
public static double gibkoordinate(ArrayList<Schacht> schaechte,int nummer) {
		Schacht schacht = schaechte.get(nummer);

		double koordinate = schacht.getxKoordinate();
		return koordinate;[/code]
dann funktioniert es. 
Genauso auch bei HaltungenTableModel für Methoden die auf haltungen zugreife.
Wenn ich auf beides zugreifen will, klappt es nicht.
Ich muss allerdings auf beides zugreifen können, wenn ich die Berechnung so realisieren will, wie ich es mir vorstelle.
Es wäre echt nett, wenn ihr mir helfen könntet, sitze jetzt schon echt lange an diesem Problem und ich dreh mich nur im Kreis.

Viele Grüße


----------



## André Uhres (1. Jul 2012)

Eine Möglichkeit wäre, einen neuen Getter in SchaechteTableModel einzubauen, der Dir die fragliche Liste zurück gibt, und dann die beiden TableModels miteinander zu verbinden, indem Du zum Beispiel die Referenz auf SchaechteTableModel and das zweite TableModel im Konstruktor übergibst. Diese Referenz speicherst Du dann in einer Instanzvariablen und kann dann darüber auf die Liste zugreifen. Die Referenz "schaechte" könntest Du dann entfernen.

Gruß,
André


----------



## bERt0r (1. Jul 2012)

Warum in aller Welt brauchst du ein eigenes Table Model für deine Daten? Nimm das DefaultTableModel.
Namen wie "Berechnungsklasse" sind immer für mich immer so ein Indikator dafür, dass hier eine Klasse für etwas gemacht wurde, was in einer Funktion erledigt werden sollte. Und selbst wenn nicht ist der Name meist immer noch schlecht gewählt. Jedenfalls wäre es nett wenn du uns mal beschreiben würdest was du eigentlich machen willst (deine Aufgabenstellung)


----------



## Harry Kane (1. Jul 2012)

ich habe zwar nicht im einzelnen verstanden was das Problem ist, aber etws ist mir aufgefallen:
In deiner Berechnungsklasse.berechneGefaelle übergibst du eine ArrayList<Schacht> und holst dir in der Berechnung einen "anfangsschacht" über 
	
	
	
	





```
Schacht anfangsschacht = Rohrnetz.getSchaechte().get(anfangsnummer)
```
. Wann und wie wird diese statische Variable der Rohrnetz-Klasse gefüllt? Inwieweit hängt sie mit der ArrayList<Schacht> zusammen, die du als Parameter übergibst?
Grundsätzlich: TableModel direkt zu implementieren ist meistens unnötig. ich würde dir raten, AbstractTableModel zu erweitern. Dadurch würdest du dir deinen selbstgescrhriebenen Mechanismus zum registrieren von Listenern sparen. TableModel zu implementieren ist nur dann nötig wenn deine Klasse bereits in einer Vererbungshierachie steckt.

Für eine weiteres verständnis von dem was in deinem Code passiert wäre die Source der Klasse Rohrnetz erforderlich.


----------



## PhilBauing (1. Jul 2012)

@ andre: ich probiere es mal so. 

@ HarrayKane: 

hier die Klasse Rohrnetz:

[Java]
package rohrnetz;

import java.util.ArrayList;

public class Rohrnetz {

	private ArrayList<Schacht> schaechte;

	private ArrayList<Haltung> haltungen;


	public Rohrnetz() {
		schaechte = new ArrayList<Schacht>();
		haltungen = new ArrayList<Haltung>();


	}


	// Haltungen bzw Schächte den jeweiligen ArrayListen zufügen.
	public void neuerSchacht(Schacht schacht) {
		this.schaechte.add(schacht);
	}

	public void neueHaltung(Haltung haltung) {
		this.haltungen.add(haltung);

	}

	public ArrayList<Schacht> getSchaechte() {
		return schaechte;
	}

	public void setSchaechte(ArrayList<Schacht> schaechte) {
		this.schaechte = schaechte;
	}

	public ArrayList<Haltung> getHaltungen() {
		return haltungen;
	}

	public void setHaltungen(ArrayList<Haltung> haltungen) {
		this.haltungen = haltungen;
	}



}[/code]

Ich dachte dass die genau durch diese Zeile gefüllt wird, weil ich ja mit getSchaechte, die ArrayList<Schacht> schaechte aufrufe, oder nicht?

In wiefern kann ich abstract TableModel benutzen? Wenn ich das erweitere und die listenerschleife wegmache, wird dem Table keine neue Zeile zugefügt.


----------



## PhilBauing (1. Jul 2012)

Niemand eine Idee? Das Projekt ist eigentlich für 4 Personen gedacht, da ein Kommilitone und ich uns schon einmal auf andere Leute verlassen haben und enttäuscht wurden, haben wir uns entschlossen das Projekt zu zweit zu bearbeiten.

Noch bevor er anfangen konnte etwas für das Projekt zutun, ist er Krankheitsbedingt ausgefallen. Daher bearbeite ich das Projekt nun alleine, ich habe diese Woche schon sehr viel hier gepostet, da zu alledem noch unser Informatiklehrstuhl bis Montag in Moskau ist. Abgabe ist heute um 00:00 Uhr. Ich finde, dafür dass ich es alleine mache(und es das erste mal ist, dass ich ein Programm schreibe), bin ich bisher schon sehr sehr weit gekommen. Bisher habe ich in meinen Posts immer um Denkanstöße gebeten, da ich mir die Option offenhalten möchte Informatik im Bauwesen zu vertiefen.

Da es mit der Zeit nun allerdings etwas knapp wird, bitte ich euch darum mir vielleicht zu helfen so große Fehler wie den obigen schnell auszumerzen, da es mich sehr daran hindert die restlichen Funktionen des Programms hinzuzufügen.

Danke schonmal.


----------



## bERt0r (1. Jul 2012)

Ideen hätt ich hundert und ich hätte - wie in deinem anderen Thread beschrieben - auch die ganze Struktur anders aufgebaut. Leider hast du dir so ziemlich den blödsten Tag für die Lieferung einer gratis Hausaufgabe ausgesucht. Heute ist EM-Finale...
Aber wenn du so viele Schicksalsschläge in deinem Projekt hinnehmen musstest, ersuch doch deinen LVA Leiter um einen Aufschub der Frist.


----------



## PhilBauing (1. Jul 2012)

Das Problem liegt darin, dass ich am Tag als sich abzeichnete, dass ich das Projekt alleine mache den Lehrstuhl sofort kontaktiert habe. Der gesamte Lehrstuhl, bis auf die Sekretärin ist in Moskau bis Montag den 02.07.

Ich habe mich auch gefragt, wieso ein Lehrstuhl so etwas in der Abgabewoche von Projekten macht, ohne die Studenten davon zu informieren. Dieses Problem habe ich gelöst (Endlich, es hat sich gestern um 16.00 aufgetan und mir dementsprechend etlich viel Zeit geraubt. Ich versuche das Programm jetzt schnellstmöglich irgendwie zusammen zu kriegen, dass es komplett ist. An Schönheit und realitätsbezug (negative Zulaufmengen z.B) muss ich dann halt sparen. 

Fußball würde ich auch gerne gucken 

Trotzdem danke für die Hilfe


----------



## Harry Kane (1. Jul 2012)

Die Herkunft von 

```
Rohrnetz.getSchaechte().get(anfangsnummer)
```
ist ungeklärt. Entweder hat die Rohrnetz-Klasse eine statische Methode getSchaechte() (davon ist in deinem Codeschnipsel nix zu sehen), oder die Klasse in der die statische Methode berechneGefaelle(...) deklariert ist, hat ein statisches Attribut Rohrnetz vom Typ Rohrnetz. ???:L
Deine Berechnungsklasse ist übrigens leer, weil zwischen der Zeile mit der Klassendeklaration und der geschweifetn Klammer, die das Ende des Definitionsblock anzeugt, nix steht. ???:L???:L
die geschweifte Klammer
Um AbstractTableModel zu nutzen, sollte es genügen, die Klassendeklaration von 

```
public class SchaechteTableModel implements TableModel
```
auf

```
public class SchaechteTableModel extends AbstractTableModel
```
zu ändern. In der

```
addSchacht(Schacht schacht)
```
Methode müsstest du statt 

```
TableModelEvent e = new TableModelEvent(this, index, index,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT);
for (int i = 0, n = listeners.size(); i < n; i++) {
    ((TableModelListener) listeners.get(i)).tableChanged(e);
}
```
das hier

```
TableModelEvent e = new TableModelEvent(this, index, index,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT);
fireTableChanged(e);
```
schreiben.
Oder einfach AbstractTableModel.fireTableDataChanged() aufrufen und die genaue veränderung nicht spezfizieren.
Das ganze sei aber nur der Vollständigkeit halber erwähnt.

Zur Funktion deiner beiden TableModels:
Wenn du in einem der TableModels die ArrayList veränderst, bekommt das andere TableModel von der Änderung zunächst mal nix mit. Ausserdem halte ich es für unklug im TableModel die Daten zu ändern. ich verwende TableModels meistens dazu, eine per se nicht-tabellarische Datenstruktur in Zeilen und Spalten zu pressen. Änderungen werden nur an der Datenstruktur vorgenommen, die ihrerseits die TableModels über die veränderung informiert, die dann wiederum events feuern und auf diese Weise ein Neuzeichnen der Tabelle veranlassen.
Ich würds so machen:
Übergebe deinen beiden TableModels eine Referenz auf das Rohrnetz, füge neuen Schaechte und Halterungen nur im Rohrnetz hinzu und sorge dafür dass die TableModels von der Änderung Wind bekommen, ungefähr so:

```
public class Rohrnetz {

    private ArrayList<RohrnetzChangeListener> listeners;
    //....

    public void addChangeListener(RohrnetzChangeListener listener) {
        listeners.add(listener);
    }

    protected void fireRohrnetzChanged() {
        //aufzurufen wen z. B. Schaechte oder Haltungen hinzugefügt wurden
        for (RohrnetzChangeListener listener : listeners) {
            listener.rohrnetzChanged();
        }
    }
}

interface RohrnetzChangeListener {

    public void rohrnetzChanged();
}
public class SchaechteTableModel extends AbstractTableModel implements RohrnetzChangeListener {

    private Rohrnetz rohrnetz;

    SchaechteTableModel(Rohrnetz rohrnetz) {
        this.rohrnetz = rohrnetz;
    }

    public int getRowCount() {
        return rohrnetz.getSchaechte().size();
    }

    public int getColumnCount() {
        return 4;
    }

    public String getColumnName(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return "Nr.";
            case 1:
                return "Tiefe";
            case 2:
                return "Durchmesser";
            case 3:
                return "Volumenstrom";
            default:
                return null;
        }
    }

    public void rohrnetzChanged() {
        fireTableDataChanged();
    }

    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return Integer.class;
            case 1:
                return Double.class;
            case 2:
                return Double.class;
            case 3:
                return Double.class;
            default:
                return null;
        }
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
        Schacht schacht = rohrnetz.getSchaechte().get(rowIndex);
        switch (columnIndex) {
            case 0:
                return rowIndex + 1;  //1. Spalte nummerierung
            case 1:
                return schacht.getTiefe(); //2. Spalte Tiefe des jeweiligen Schachtes. Getter der Klasse Schacht
            case 2:
                return schacht.getDurchmesser(); //3. Der Durchmesser. Getter der Klasse Schacht

            case 3:
                return schacht.getZulaufmenge(); //3. Zulaufmenge. Getter der Klasse Schacht
            default:
                return null;
        }
    }
}
class MainIrgendwas{
    public MainIrgendwas(){
        Rohrnetz rohrnetz = new Rohrnetz();
        SchaechteTableModel model = new SchaechteTableModel(rohrnetz);
        rohrnetz.addChangeListener(model);
    }
}
```
Abschliessend: die berechneGefaelle(...) sieht so aus, als wäre sie in der Rohrnetz-Klasse gut aufgehoben. Als Parameter müsste man nur 
	
	
	
	





```
int nummer
```
 übergeben. Die haltungen- und schaechte-ArrayLists kennt die Rohrnetz-Klase sowieso.


----------



## PhilBauing (2. Jul 2012)

hey, 

ich war heute Morgen beim Lehrstuhl und habe eine aufschiebung der Frist um einen Monat erwirken können. Dazu wird bei der Bewertung berücksichtigt, dass ich ein Projekt alleine bearbeite, was eigentlich für vier Personen gedacht ist. 
Da ich nun nicht mehr unter Zeitdruck stehe, werde ich es natürlich weiter so handhaben, dass wenn ich hier Poste, ich genau schildere wo mein Problem liegt, was ich bisher ausprobiert habe und was ich denke woran es liegen könnte, da ich, wie bereits geschildert großen Wert darauf lege, viel bei dem Projekt zu lernen. 

Es verunsichert mich jetzt gerade nur sehr - und das würde ich gerne geklärt haben, bevor ich weiter programmiere - dass mehrere Leute das Programm ganz anders strukturiert hätten. Ich verstehe nicht, was an meiner Struktur unvorteilhaft ist oder warum ihr es anders machen würdet.
 Ich habe objektorientierte Programmierung so verstanden, dass möglichst wenige Verbindungen unter den Klassen bestehen, die Klassen aber trotzdem so aufgebaut sind, dass sie nicht universell einsetzbar sind, sonder auf das Objekt Rohrnetz abgestimmt sind, verstehe ich das richtig?

Edit: 

Weil danach gefragt wurde, hier die genaue Aufgabenstellung. 

Aufgabenstellung.pdf

Ich werde jetzt erst einmal mein UML-Diagramm und meinen Quelltext aufräumen und letzteres kommentieren, falls mir jemand helfen möchte und sich ein besseres Bild von meinem aktuellen Projekt machen möchte. 

Viele Grüße


----------



## Harry Kane (2. Jul 2012)

Ich habs mal überflogen.
Zusammen mit den Infos aus deinem anderen Thread sieht es jetzt so aus:
1. Klasse Schacht mit den Eigenschaften x, y, Tiefe, Zulaufmenge, und offenbar ein Flag, mit dem überprüft werden kann, ob der Schacht so wie es sich gehört, an einer Haltung bzw. einem Abfluss hängt.
2. Klasse Haltungen: hat zwei Schächte, einen Anfangs- und einen Endschacht. Aus den Koordinaten des Anfangs- und Endschachtes lässt sich das Gefälle der Haltung berechnen. Ausserdem hat eine Haltung noch keinen, einen oder mehrere "Haltungsvorgänger", die in Strömungsrichtung vor der aktuellen Haltung liegt.
3. Der Anfangsschacht der aktuellen Haltung #wird zum Endschacht eventueller "Vorgängerhaltungen".
4. Die Flussmenge durch eine Haltung ergibt sich aus der Flussmenge der "Vorgängerhaltungen" sowie dem Durchfluss durch den Anfangsschacht.

Aktionen, die durch die Klasse Rohrnetz kontrolliert werden können:
1. Neue Schächte und Haltungen müssen hinzugefügt werden können. Zunächst hängen sie nur teilnahmslos in der Gegend herum.
2. Ein Schacht muss mit einer Haltung verbunden werden können. Wenn das geschieht, wird in dem Schacht ein Flag gesetzt, der anzeigt, dass der Schacht jetzt einen Abfluss hat (wichtig für Plausibilitätsaprüfung). Der Schacht wird zum Anfangsschacht der Haltung und ersetzt dabei einen ev. vorhandenen Schacht, der dann nicht mehr mit einer Haltung verbunden ist. Ausserdem wird der Schaht zum Endschacht eventueller "Vorgängerhaltungen" und ersetz dabei einen ev. vorhandenen Endschacht. Ein direktes Setzen des Endscchts ist wahrscheinlich nicht sinnvoll. Bei einer Plausibilitätsprüfung sollte sichergestellt werden, dass der Endschacht einer Haltung gleich dem Anfangsschacht seines Nachfolgers ist bzw. dass der Anfangsschacht einer Haltung gleich dem Endschacht aller Vorgängerhaltungen ist.
3. Eine Haltung muss mit einer oder mehrerer Vorgängerhaltungen verbunden werden können.

Wie in deinem anderen Thread ebschrieben, sollte es genügen, einer Haltung bspw. den Index des ASnfgangs- und Endschachtes mitzugeben. Dann muss die Haltung aber imstande sein, mit diesen Indices wieder auf die Schacht-Objekte zugreifen zu könne, um deren Koordinaten auszulesen und daraus das Gefälle der Haltung zu berechnen (Schaechte verlaufen offenbar streng vertikal. Um das zu erreichen, muss jede Haltung eine Referenz auf das Rohrnetz bekommen. Ein Schacht muss nicht zwingend wissen mit welcher Haltung er verbunden ist, er muss nur wissen, ob er mit einer Haltung verbunden ist.

Noch ein Wort zu deiner Klasse Rohrnetz: In der gegenwärtigen Fassung könnte jemand die ArrayList mit den Haltungen und Schächten nach belieben verändern, Objekte löschen, umsortieren, usw. Das ist sicherlich nicht beabsichtigt. Ich würde den Zugriff auf bspw.- die Schaechte so gestalten, um den direkten ZUgriff auf die ArrayList zu unterbinden.

```
public class Rohrnetz {
  
    private ArrayList<Schacht> schaechte;

    public int gibAnzahlSchaechte(){
        return schaechte.size();
    }
    public Schacht gibSchacht(int index){
        return schaechte.get(index);
    }
    
}
```


----------



## PhilBauing (3. Jul 2012)

Hey, 

ich hatte mir überlegt, die Plausibilitätsprüfung wegzulassen und stattdessen in der Benutzeroberfläche den Benutzer über Komboboxen festlegen zu lassen, von wo und wohin eine Haltung läuft. Ich habe es so gemacht, dass wenn man eine Haltung erzeugt hat, dass dann in der Anfangskombobox, der Wert der Endkombobox voreingestellt ist. Hat das nachteile gegenüber den Flags?

Eine weitere Sache, wo ich bisher noch nicht ganz hinter gestiegen bin, ist bei dir Punkt vier. 
Ich schaffe es zwar, die Gesamtzulaufmenge zu berechnen, ich hab aber noch ziemliche Probleme damit das Konzept Haupt- und Nebenhaltungen so umzusetzen, dass sich individuell die Zulaufmengen für die einzelnen Haltungen berechnen lassen. 

Beispiel:

Ein User erzeugt 4 haltungen und erzeugt 2 Haupthaltungen. Ein Schacht ist noch frei, dementsprechend muss der Benutzer jetzt noch diesen Schacht mit dem Rest verbinden. Sagen wir er verbindet diesen mit Schacht zwei. Dann bekommt die Haupthaltung zwei (Mit Anfangsschacht zwei) ja neben der Zulaufmenge von Schacht zwei und Haltung eins noch die Zulaufmenge von Nebenhaltung eins. Kompliziert oder? ;P

Ich habe bei Java ist auch eine Insel etwas über Schnittstellen gelesen, da wird das Beispiel "buyable" genannt. Ist das vielleicht genau das was ich brauche? Eine Schnittstelle die einer Haltung sagt, dass sie nicht nur eine Vorgängerhaltung sondern möglicherweise auch Vorgängernebenhaltungen hat.
Danke für die Hilfe


Viele Grüße und einen schönen sonnigen Dienstag


----------



## André Uhres (3. Jul 2012)

Da es ja jetzt nicht mehr viel mit dem ursprünglichen konkreten Problem zu tun hat ("Auf gefüllte ArrayList zugreifen", was anscheinend gelöst ist), würde ich vorschlagen, bei einem eventuell auftretenden neuen konkreten Problem auch ein neues Thema zu eröffnen .

Gruß,
André


----------

