# JTable - Tabelle füllen mit einer ArrayList



## Ollek (11. Jan 2010)

Hallo liebe Leute,

ich programmiere mir gerade eine Movie Verwaltung, für meine Sammlung.
Allerdings bleibe ich gerade daran hängen, dass ich meine Daten nicht in der JTable angeziegt bekomme.
Ich lese die Daten aus der MySQL Datenbank raus und packe diese in eine ArrayList die ich an das Model der Table übergebe. Wie bekomme ich diese angezeigt? Wo liegt mein Fehler?

Fehlen mir dort eventuell Listener??

Hier der Code:

```
package de.mymoviecollection.view;

import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
import de.mymoviecollection.core.Movie;


public class MyMCTableModel extends AbstractTableModel {
	
	private ArrayList<Movie> movieList;
	
	@Override
	public int getColumnCount() {
		return 7;
	}

	@Override
	public int getRowCount() {
		return 200;
	}

	public Object getValueAt(int rowIndex, int columnIndex ) {
		
		for(int i = 0; i < movieList.size(); i++){
			
			switch ( columnIndex ){
				case 0: return movieList.get(i).getTitleGerman();
				case 1: return movieList.get(i).getFormat();
				case 2: return movieList.get(i).getGenre();
				case 3: return movieList.get(i).getCountry();
				case 4: return movieList.get(i).getRuntime();
				case 5: return movieList.get(i).getFsk();
				case 6: return movieList.get(i).getRating();
			}
		}
		return null;
		
	
	}
	
	public String getColumnName( int iColumn ){
		switch ( iColumn ){
		case 0: return "Titel";
		case 1: return "Format";
		case 2: return "Genre";
		case 3: return "Land";
		case 4: return "Länge";
		case 5: return "FSK";
		case 6: return "Rating";
		default: return null;
		}
		
	
	}

	public void getAllMovies(ArrayList movies){
		movieList = movies;
		
	}

}
```

Code von der JTable:


```
package de.mymoviecollection.view;

import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class MyMCTablePanel extends JPanel {

	private JTable table = new JTable();
	private MyMCTableModel model;
	
	
	public MyMCTablePanel(){
		
		setPreferredSize( new Dimension(600, 500));
		setBackground(Color.DARK_GRAY);
	
		model = new MyMCTableModel();
		
		table.setModel( model );
		
		JScrollPane scrollPane = new JScrollPane( table );
		
		
		add(scrollPane);
		setVisible(true);
	}
}
```

Hoffe ihr könnt mir dort weiterhelfen.

habe mir auch das Tutorial durchgelesen, was unter der FAQ zufinden ist.

Besten Gruß


----------



## Michael... (11. Jan 2010)

Der Fehler liegt vermutlich in der getValueAt des Models. Die for-Schleife ist hier völlig fehl am Platz
Muss eher so lauten:

```
public Object getValueAt(int rowIndex, int columnIndex ) {            
            switch ( columnIndex ){
                case 0: return movieList.get(rowIndex).getTitleGerman();
                ...
        }
        return null;
}
```


----------



## Ollek (11. Jan 2010)

Habe es jetzt mal geändert. Klappt allerdings immer noch nicht, der baut das JFrame jetzt zwar auf, aber im Hintergrund bekomme ich immer noch etliche Exceptions ausgegeben.

Habe den Exceptions-Stack mal kopiert und poste ihn hier.
Der spricht von einer Unknown Source.

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at de.mymoviecollection.view.MyMCTableModel.getValueAt(MyMCTableModel.java:25)
	at javax.swing.JTable.getValueAt(Unknown Source)
	at javax.swing.JTable.prepareRenderer(Unknown Source)
	at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
	at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
	at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
	at javax.swing.plaf.ComponentUI.update(Unknown Source)
	at javax.swing.JComponent.paintComponent(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
	at javax.swing.RepaintManager.paint(Unknown Source)
	at javax.swing.JComponent.paintForceDoubleBuffered(Unknown Source)
	at javax.swing.JViewport.paintView(Unknown Source)
	at javax.swing.JViewport.windowBlitPaint(Unknown Source)
	at javax.swing.JViewport.setViewPosition(Unknown Source)
	at javax.swing.plaf.basic.BasicScrollPaneUI$Handler.vsbStateChanged(Unknown Source)
	at javax.swing.plaf.basic.BasicScrollPaneUI$Handler.stateChanged(Unknown Source)
	at javax.swing.DefaultBoundedRangeModel.fireStateChanged(Unknown Source)
	at javax.swing.DefaultBoundedRangeModel.setRangeProperties(Unknown Source)
	at javax.swing.DefaultBoundedRangeModel.setValue(Unknown Source)
	at javax.swing.JScrollBar.setValue(Unknown Source)
	at javax.swing.plaf.basic.BasicScrollBarUI$TrackListener.setValueFrom(Unknown Source)
	at javax.swing.plaf.basic.BasicScrollBarUI$TrackListener.mouseDragged(Unknown Source)
	at java.awt.Component.processMouseMotionEvent(Unknown Source)
	at javax.swing.JComponent.processMouseMotionEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Eventuell noch ein paar weitere infos dazu, ich habe eine Methode die eine ArrayList zurück gibt:


```
public ArrayList selectAllMovies(Movie thisMovie){
		/* initialize ArrayList forMovies */
		movieList = new ArrayList<Movie>();
		
		try {
			PreparedStatement pStatement = DBConnection.connection.prepareStatement(
			"SELECT titleGerman, titleOriginal, country, format, genre, runtime, fsk, year FROM movie");
			
			ResultSet rsMovie = null;
			rsMovie = pStatement.executeQuery();
			
			while(rsMovie.next()){
			
			/* local Movie */	
			Movie newMovie = new Movie();
			
			newMovie.setTitleGerman( rsMovie.getString("titleGerman"));
			newMovie.setTitleOriginal(rsMovie.getString("titleOriginal"));
			newMovie.setCountry(rsMovie.getString("country"));
			newMovie.setFormat(rsMovie.getString("format"));
			newMovie.setGenre(rsMovie.getString("genre"));
			newMovie.setRuntime(rsMovie.getInt("runtime"));
			newMovie.setFsk(rsMovie.getInt("fsk"));
			newMovie.setYear(rsMovie.getInt("year"));
			
			/* add Movie to Movie-ArrayList */
			movieList.add(newMovie);
	
			}
			System.out.println(movieList.size() + " Filme gefunden und in die Liste eingetragen.");
			
		for ( int i = 0; i < movieList.size(); i++){
			System.out.println(movieList.get(i).getTitleGerman() + ", " + movieList.get(i).getFormat());
		}
			/* close ResultSet and PreparedStatement */
			rsMovie.close();
			pStatement.close();
			
		} catch (SQLException e) {
			System.err.println("Fehler: beim Zugriff auf die Filmdaten ");
			e.printStackTrace();
			
		}
		return movieList;
	}
```

Diese wird in einer anderen Klasse aufgerufen un direkt an die Methode aus dem model weitergegeben. und in eine vorhandene ArrayList gesetzt.


```
/* initialize Movie */
		Movie thisMovie = new Movie();
				
		/* connect Database */
		DBConnection.connect2DB();
		
		/* initialize DBOperations */
		DBOperations dbOperations = new DBOperations();
		try {
			MyMCTableModel tableModel = new MyMCTableModel();			
			tableModel.getAllMovies(dbOperations.selectAllMovies(thisMovie));
			
		} catch (Exception e) {
			DBConnection.disconnectDB();
		}
```

Eventuell liegt ja dort ein Fehler vor, weswegen er die die Unknown Source anmeckert.

Besten Gruß


----------



## Michael... (11. Jan 2010)

> ```
> @Override
> public int getRowCount() {
> return 200;
> ...


Du gibst im Model eine feste Zeilenanzahl zurück. Hier muss natürlich die Anzahl der Listenelemente zurückgegeben werden.


----------



## Ollek (11. Jan 2010)

```
@Override
	public int getRowCount() {
		return movieList.size();
	}
```

Wenn ichs so schreibe, dann meckert er auch wieder von wegen Unknown source, ich glaube der hat ein problem mit der ArrayList, das dort keine Daten vorhanden sind, aber wo steckt denn dort der fehler...?


----------



## Michael... (11. Jan 2010)

Ollek hat gesagt.:


> wo steckt denn dort der fehler...?


Schwer zu sagen. Erstell doch manuell eine ArrayList (ohne Datenbankabfrage) und übergib die dem Model.


----------



## Ollek (11. Jan 2010)

Sobald ich mehrere Adds in der ArrayList habe meckert er, bei einem fügt er in der erste Spalte und in allen Zeilen das Wort ein was ich in movieList.add(0, "Test"); hinzugefügt habe.


----------



## Michael... (11. Jan 2010)

Nochmal zum Thema NullPointerException: Kann es sein, dass die Tabelle angezeigt wird bevor die ArrayList befüllt ist? 
In dem Fall würde es schon helfen in Zeile 10 des TableModels eine leer Liste anzulegen:
[JAVA=10]private ArrayList<Movie> movieList = new ArrayList<Movie>();[/code]


----------



## Ollek (11. Jan 2010)

klappt auch nicht :-(


----------



## Spin (11. Jan 2010)

```
private ArrayList<Movie> movieList;
```


Der Fehler steckt doch schon im ersten Code. Dort fragst du eine Liste ab, die nicht gefüllt ist. Daher auch eine NullpointerException.


Fülle dein Table Model mit Daten !


----------



## Ollek (11. Jan 2010)

Hast du da eventuell nen Codebeispiel für mich?

Ich habe die ArrayList doch nur deklariert, gefüllt habe ich diese doch dann im unteren teil durch die Methode.

Oder denke ich dort gerade völlig falsch??? :shock:


----------



## Michael... (11. Jan 2010)

```
mport java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class ArrayListTableModel extends JFrame {
	
	public static void main(String[] args) {
		new ArrayListTableModel();
	}
	
	public ArrayListTableModel() {
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setBounds(50, 50, 200, 150);
		ArrayList<Movie> list = new ArrayList<Movie>();
		list.add(new Movie("Terminator", "ab 16"));
		list.add(new Movie("Bambi", "ohne"));
		MyMCTableModel model = new MyMCTableModel();
		model.setList(list);
		this.getContentPane().add(new JScrollPane(new JTable(model)));
		setVisible(true);
	}
	
	class Movie {
		private String title, fsk;
		
		public Movie(String title, String fsk) {
			this.title = title;
			this.fsk = fsk;
		}
		public String getTitle() {return title;}
		
		public String getFSK() {return fsk;}
	}

	class MyMCTableModel extends AbstractTableModel {

		private ArrayList<Movie> movieList = new ArrayList<Movie>();

		public int getColumnCount() {return 2;}

		public int getRowCount() {return movieList.size();}

		public Object getValueAt(int row, int column) {
			switch (column) {
			case 0:	return movieList.get(row).getTitle();
			case 1:	return movieList.get(row).getFSK();
			}
			return null;
		}

		public String getColumnName(int iColumn) {
			switch (iColumn) {
			case 0:	return "Titel";
			case 1:	return "FSK";
			}
			return null;
		}
		
		public void setList(ArrayList<Movie> movieList) {
			this.movieList = movieList;
		}
	}
}
```


----------



## Ollek (11. Jan 2010)

Habe meinen Source nun so angepasst, wie du ihn hier gepostet hast... Allerdings sehe ich nun keine Zeilen mehr in der Tabelle ;-) ;(


----------



## Michael... (11. Jan 2010)

Schmeiss doch mal aus Deinem Code alles überflüssige raus und poste ihn hier mal.
Sollte aber noch ausführbar sein.


----------



## Ollek (11. Jan 2010)

Mach ich später von zu Hause, ich glaube das Problem ist, dass er die leere ArrayListe nicht füllt, bzw. erst zu spät füllt und diese dann nicht aktualisiert...

Ausführen kann ichs jetzt ohne Fehlermeldungen....Nur die Tabelle zeigt mit keine Zeilen an... Denke das liegt an der leeren ArrayList


----------



## Ollek (11. Jan 2010)

Hier die Klassen:

MyMCTableModel

```
public class MyMCTableModel extends AbstractTableModel {
	
	private ArrayList<Movie> movieList = new ArrayList<Movie>();

	
	@Override
	public int getColumnCount() {
		return 7;
	}

	@Override
	public int getRowCount() {
		return movieList.size();
	}

	public Object getValueAt(int rowIndex, int columnIndex ) {
		switch ( columnIndex ){
			case 0: return movieList.get( rowIndex ).getTitleGerman();
			case 1: return movieList.get( rowIndex ).getFormat();
			case 2: return movieList.get( rowIndex ).getGenre();
			case 3: return movieList.get( rowIndex ).getCountry();
			case 4: return movieList.get( rowIndex ).getRuntime();
			case 5: return movieList.get( rowIndex ).getFsk();
			case 6: return movieList.get( rowIndex ).getRating();
		}
		return null;
	}
	
	public String getColumnName( int iColumn ){
		switch ( iColumn ){
		case 0: return "Titel";
		case 1: return "Format";
		case 2: return "Genre";
		case 3: return "Land";
		case 4: return "Länge";
		case 5: return "FSK";
		case 6: return "Rating";
		default: return null;
		}
		
	
	}

	public void setMovieList(ArrayList<Movie> movieList){
		this.movieList = movieList;
	}

}
```

MyMCTablePanel

```
public class MyMCTablePanel extends JPanel {

	private JTable table = new JTable();
	private MyMCTableModel model;
	
	
	public MyMCTablePanel(){
		
		setPreferredSize( new Dimension(600, 500));
		setBackground(Color.DARK_GRAY);
	
		model = new MyMCTableModel();
		
		table.setModel( model );
		
		JScrollPane scrollPane = new JScrollPane( table );
		
		
		add(scrollPane);
		setVisible(true);
	}
}
```

Main-Class

```
public static void main(String[] args) {
		
		/* set look and feel */
		LookAndFeelSettings.setNativeLookAndFeel();
		
		/* load icons */
		IconCache.init();
		
		/* initialize Movie */
		Movie thisMovie = new Movie();   
				
		/* connect Database */
		DBConnection.connect2DB();
		
		/* initialize DBOperations */
		DBOperations dbOperations = new DBOperations();
		try {
			MyMCTableModel model = new MyMCTableModel();			
			model.setMovieList(dbOperations.selectAllMovies(thisMovie));
			
		} catch (Exception e) {
			DBConnection.disconnectDB();
		}
		
		
		final MyMCGUI gui = new MyMCGUI();
		gui.showMovieInformation(thisMovie);
		
		DBConnection.disconnectDB();
		
		/* load gui */
		SwingUtilities.invokeLater(new Runnable(){
			public void run(){
				gui.setVisible(true);
			}
		});
```

In der Movie-Klasse sind nur Getter und Setter.

Also der Run klappt ohne Probleme, allerdings werden mir die Filme nicht in der Liste angezeigt. Ist eine lehre Tabelle, ohne Zeilen.. Aber die tabelle hat die Überschriften.

Findet jemand dort noch einen Fehler? ich komme nicht weiter. Wie kann ich die ArrayList updaten?? :rtfm:

Besten Gruß


----------



## Michael... (12. Jan 2010)

Vielleicht ist Deine Liste ja leer!?!

Überprüfe doch mal 
	
	
	
	





```
dbOperations.selectAllMovies(thisMovie)
```
 in Zeile 19 der main.
Was wird bei 
	
	
	
	





```
System.out.println(dbOperations.selectAllMovies(thisMovie).size());
```
 ausgegeben.
Eventuell wird sogar beim eine Exception geworfen, die Du zwar abfängst, aber nicht ausgibst:
Zeile 21ff in der main
Lass Dir die potentielle Exception per 
	
	
	
	





```
e.printStackTrace()
```
 ausgeben.


----------



## Ollek (12. Jan 2010)

Habe auch das ausprobiert.
Es wird mir die richtige Anzahl an Filmen ausgegeben.
Und eine Exception bekomme ich auch nicht.

Entweder es läuft was bei der Übergabe der ArrayListen falsch, oder er nimmt am Anfang die leere ArrayListe und zeigt deswegen keine Zeilen bzw. Filme in der Table an....???:L


----------



## Michael... (12. Jan 2010)

Sorry, Deine Klasse erbt ja von AbstractTableModel.
Da sollte eventuell ein Aufruf von 
	
	
	
	





```
fireTableDataChanged();
```
 in die setMovieList des Models helfen:


```
public void setMovieList(ArrayList<Movie> movieList){
        this.movieList = movieList;
        fireTableDataChanged();
}
```


----------



## Ollek (12. Jan 2010)

schade, klappte auch nicht...

Das habe ich gestern auch schon in der Table-Klasse probiert, aber auch erfolglos :-(

Habe gerade mal aus Testzwecken eine feste Zeilen-Anzahl angegeben und zwar:


```
public int getRowCount() { return 2; }
```

Dann gabs wieder Probleme beim ausführen. Und zwar baut er dann ein Fenster auf, allerdings mit den Exceptions, welche ich im oben geposteten Beitrag schon eingefügt habe.
Wenn ich dann mit der Maus über das Fenster fahre, baut sich dort wo ich dem Mauszeiger entlang gehe nach und nach das GUI auf bzw. es wird sichtbar (s. Screenshot). Allerdings bekomme ich dann immer weitere Exceptions. :autsch:

Also irgendwas stimmt da vorne und hinten nicht, leider ist mein know How dafür nicht da :-(

Habe das Fenster mal als Screenshot angehängt.


----------



## Michael... (12. Jan 2010)

Kann es sein, dass Du mit zwei Models arbeitest?
Du erzeugst eines in der main und eines im Konstruktor von MyMCTablePanel.
Ich sehe aber nirgends, dass das Model aus der main an MyMCTablePanel übergeben wird.


----------



## Ollek (12. Jan 2010)

Das war der Knackpunkt!! :toll:

Es klappt, aber eine Frage hätte ich noch, wie ichs jetzt gemacht habe.. Ist das sauber? :rtfm:

Habe nur das, was ich neu programmiert habe reingepackt...
Natürlich ist das noch kein entgültiger Code.. Aber so vom Übergeben her..?


```
public class MyMC {

	public static void main(String[] args) {
				
		/* connect Database */
		DBConnection.connect2DB();
		
		/* initialize DBOperations */
		DBOperations dbOperations = new DBOperations();
		
		
		
		final MyMCGUI gui = new MyMCGUI();
		MyMCTableModel thisModel = new MyMCTableModel();
		try {
			gui.showMovieInformation(thisMovie);
			gui.setMyMCTable(thisModel);
			thisModel.setMovieList(dbOperations.selectAllMovies(thisMovie));
			
		} catch (Exception e) {
			DBConnection.disconnectDB();
			e.printStackTrace();
		}
		
		/* disconnect Database */
		DBConnection.disconnectDB();

}
```


```
public class MyMCGUI extends JFrame {

	MyMCDetailsPanel detailPanel;
	MyMCTablePanel listPanel;
	
	public MyMCGUI(){
		super("My Movie Collection");

		
		listPanel = new MyMCTablePanel();
		this.add(BorderLayout.WEST, listPanel);
		
	
	public void setMyMCTable(MyMCTableModel thisModel){
		listPanel.setTableModel(thisModel);
	}
```


```
public class MyMCTablePanel extends JPanel {

	private JTable table = new JTable();
	JScrollPane scrollPane;
		
	public MyMCTablePanel(){
		
		setPreferredSize( new Dimension(600, 500));
		setBackground(Color.DARK_GRAY);
	}
	
	public void setTableModel(MyMCTableModel thisModel){
		
		table.setModel( thisModel );
		
		scrollPane = new JScrollPane( table );
		
		add(scrollPane);
		setVisible(true);	
	}
}
```

Danach kann ich es auch als ERLEDIGT markieren... ;-)

Danke dir für deine Geduld und die Hilfe.. war wohl nen etwas schwieriger Fall


----------



## Michael... (13. Jan 2010)

Ollek hat gesagt.:


> Es klappt, aber eine Frage hätte ich noch, wie ichs jetzt gemacht habe.. Ist das sauber? :rtfm:



Naja, man könnte noch ein bisschen aufräumen ;-)

In der main() würde ich:
- das TableModel erstellen
- zur Datenbank verbinden und das Model befüllen
- ein GUI-Objekt erzeugen und dabei das Model per Konstruktor übergeben

Der Aufruf von 
	
	
	
	





```
DBConnection.disconnectDB();
```
 im catch ist eigentlich überflüssig, da die Methode direkt im Anschluss sowieso aufgerufen wird.

In der Klasse MyMCGUI würde ich den Konstruktor ändern (damit das TableModel übergeben werden kann). Beim Erstellen des TablePanels würde ich ebenfalls das Model per Konstruktor weitergeben.

In der Klasse MyMCTablePanel ebenfalls den Konstruktor ändern...
das setVisible(true) ist überflüssig.

Also im Prinzip alles so anpassen, dass direkt bei Erzeugung der Objekte das TableModel mit übergeben wird und die Verteilung auf zwei Schritte aufheben. Denn ohne TableModel nützt Dir ja das TablePanel auch nichts. Dennoch könntest Du die setModel()-Methoden (in angepasster Form) beibehalten, falls Du zu einem späteren Zeitpunkt im Programmablauf mal ein anderes Model darstellen willst.


----------

