# JTable und AbstractTableModel



## infboy (31. Dez 2012)

Hallo,
ich habe eine Klasse "NameWindow" die eine Tabelle beinhaltet. 
Ich habe auch eine Klasse "NameWindowTableModel" die eine AbstractTableModel für die Tabelle in "NameWindow" darstellen soll. (ich hoffe ich habe sie richtig implementiert da ich swing-Anfänger bin)
Jetzt möchte ich die Tabelle in "NameWindow" mit der selbst implementierte AbstractTableModel verbinden. Ich weiss nur nicht wie?
Habe im net gelesen, dass man in "NameWindow" eine Variable von dem Typ "NameWindowTableModel" implementieren soll. Dadurch sollte man das Problem einfach lösen können.(habe das gemacht und auskommentiert. line 17)
Weiss aber jetzt nicht genau wie und wo man mit dieser Variable umgehen soll und ob es überhaupt richtig ist, oder man es grundsätzlich anders machen muss?

Wäre für jede Hilfe Dankbar!

Anbei die zwei Klassen:

NameWindow:

```
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;


public class NameWindow extends JFrame {
	
	
	/*
	 * die auskommetierte Variable
	 */
//	private static NameWindowTableModel nameTableModel;

	private JPanel contentPane;
	private JTable table;
	private JScrollPane scrollPane;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					NameWindow frame = new NameWindow();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public NameWindow() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		scrollPane = new JScrollPane();
		scrollPane.setBounds(10, 11, 251, 100);
		contentPane.add(scrollPane);
		
		table = new JTable();
		table.setModel(new DefaultTableModel(
			new Object[][] {
				{null, null, null},
				{null, null, null},
				{null, null, null},
				{null, null, null},
				{null, null, null},
			},
			new String[] {
				"New column", "New column", "New column"
			}
		));
		scrollPane.setViewportView(table);
	}
}
```

NameWindowTableModel:

```
import javax.swing.table.AbstractTableModel;


public class NameWindowTableModel extends AbstractTableModel {

//	@Override
//	public int getColumnCount() {
//		// TODO Auto-generated method stub
//		return 0;
//	}
//
//	@Override
//	public int getRowCount() {
//		// TODO Auto-generated method stub
//		return 0;
//	}
//
//	@Override
//	public Object getValueAt(int rowIndex, int columnIndex) {
//		// TODO Auto-generated method stub
//		return null;
//	}
	
	
	public int getColumnCount(){
		return 3;
	}
	
	
	public int getRowCount(){
		return 25;
	}
	
	public Class<?> getColumnClass(int columnIndex){
		switch(columnIndex){
		case 0: return boolean.class;
		case 1: return String.class;
		case 2: return String.class;
		default: throw new IllegalArgumentException("Falsche Spalte");
		}
	}
	
	public String getColumnName(int columnIndex){
		switch(columnIndex){
		case 0: return "Verheiratet?";
		case 1: return "Name";
		case 2: return "Nachname";
		default: throw new IllegalArgumentException("Falsche Spalte");
		}
	}
	
	public boolean isCellEditable(int rowIndex, int columnIndex){
		switch(columnIndex){
		case 0: return true;
		case 1: return true;
		case 2: return true;
		default: throw new IllegalArgumentException("Falsche Spalte");
		}
	}
	
	public Object getValueAt(int rowIndex, int columnIndex) {
        switch(columnIndex){
        case 0: return null;
        case 1: return null;
        case 2: return null;
        default: throw new IllegalArgumentException("Falsche Zeile oder Spalte");
        }
	}

}
```


----------



## bERt0r (31. Dez 2012)

Ich glaube du würdest dir mit einem DefaultTableModel viel leichter tun.


----------



## infboy (31. Dez 2012)

ja, in diesem Fall ja!
Aber ich will es lernen!


----------



## Camino (31. Dez 2012)

Du hast in Zeile 17 nur die Deklarierung des TableModels auskommentiert. Der Tabelle weist du ein neues DefaultTableModel zu, was mit deinem anderen TableModel garnichts zu tun hat. Das heisst, wenn du ein eigenes TableModel anlegst und erstellst, dann musst du das natürlich auch der Tabelle mit setModel(tableModel) übergeben.


----------



## infboy (31. Dez 2012)

also in NameWindow statt


```
table.setModel(new DefaultTableModel(
			new Object[][] {
				{null, null, null},
				{null, null, null},
				{null, null, null},
				{null, null, null},
				{null, null, null},
			},
			new String[] {
				"New column", "New column", "New column"
			}
		));
```

einfach linie 17 einkommentieren und folgendes schreiben


```
table.setModel(nameTableModel);
```

Das funktioniert aber immernoch nicht


----------



## Camino (31. Dez 2012)

infboy hat gesagt.:


> einfach linie 17 einkommentieren und folgendes schreiben
> 
> 
> ```
> ...



Nur das einkommentieren und deklarieren reicht so nicht. Du musst auch von dem TableModel ein Objekt erstellen. Also entweder

```
table.setModel(new NameTableModel());
```
oder

```
NameTableModel nameTableModel = new NameTableModel()
table.setModel(nameTableModel);
```
schreiben. Dann müsstest du aber in dem TableModel auch noch Daten zur Verfügung stellen, welche in den Zellen angezeigt werden sollen.


----------



## ARadauer (31. Dez 2012)

Dein Table Model braucht mal Daten... wo bekommt es den die her?

Der schöne Vorteil von einem eigenen Table Model ist, dass man mit eigenen Objekten arbeiten kann und nicht mit irgendwelchen Object[][] herum wurschteln muss. Ist zwar oft etwas aufändiger, aber die meiste Zeit sind wir dabei irgend etwas nachzuvollziehen bzw fehler zu suchen,.. also die paar Minuten für ein Objekte und ein eigenes Table Model rechnen sich schnell..

Also was wollen wir anzeigen? Personen?

zb so..


```
public class Person {
	private String name;

	private String vorname;
	private boolean verheiratet;

	public Person(String vorname, String name, boolean verheiratet) {
		super();
		this.vorname = vorname;
		this.name = name;
		this.verheiratet = verheiratet;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getVorname() {
		return vorname;
	}

	public void setVorname(String vorname) {
		this.vorname = vorname;
	}

	public boolean isVerheiratet() {
		return verheiratet;
	}

	public void setVerheiratet(boolean verheiratet) {
		this.verheiratet = verheiratet;
	}

}
```
klar oder?

gut dann halten wir mal eine liste in unserem model und greifen auf die daten zu...


```
import java.util.ArrayList;
import java.util.List;

import javax.swing.table.AbstractTableModel;

public class NameWindowTableModel extends AbstractTableModel {

	List<Person> personen = new ArrayList<Person>();

	public int getColumnCount() {
		return 3;
	}

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

	public Class<?> getColumnClass(int columnIndex) {
		switch (columnIndex) {
		case 0:
			return boolean.class;
		case 1:
			return String.class;
		case 2:
			return String.class;
		default:
			throw new IllegalArgumentException("Falsche Spalte");
		}
	}

	public String getColumnName(int columnIndex) {
		switch (columnIndex) {
		case 0:
			return "Verheiratet?";
		case 1:
			return "Name";
		case 2:
			return "Nachname";
		default:
			throw new IllegalArgumentException("Falsche Spalte");
		}
	}

	public boolean isCellEditable(int rowIndex, int columnIndex) {
		switch (columnIndex) {
		case 0:
			return true;
		case 1:
			return true;
		case 2:
			return true;
		default:
			throw new IllegalArgumentException("Falsche Spalte");
		}
	}

	public Object getValueAt(int rowIndex, int columnIndex) {
		Person person = personen.get(rowIndex);
		switch (columnIndex) {
		case 0:
			return person.isVerheiratet();
		case 1:
			return person.getVorname();
		case 2:
			return person.getName();
		default:
			throw new IllegalArgumentException("Falsche Zeile oder Spalte");
		}
	}

	public void setData(List<Person> personen) {
		this.personen = personen;
		fireTableDataChanged(); // wir sagen der JTable die Daten haben sich geändert!
	}

}
```
ok? also dieses fireTableDataChanged ist interessant, kannst in der api gerne nachlesen was AbstractTableModel usw noch so bietet... eigentlich ganz einfach...

gut jetzt noch in der view die daten setzen...


```
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;
 
public class NameWindow extends JFrame {
    
    
    
  private NameWindowTableModel nameTableModel; //nicht static!
 
    private JPanel contentPane;
    private JTable table;
    private JScrollPane scrollPane;
 
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    NameWindow frame = new NameWindow();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
 
    /**
     * Create the frame.
     */
    public NameWindow() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 11, 251, 100);
        contentPane.add(scrollPane);
        
        table = new JTable();
        nameTableModel = new NameWindowTableModel();
        table.setModel(nameTableModel);
        scrollPane.setViewportView(table);
        
        loadData();
    }

	private void loadData() {
		//in der praxis greifen wir hier hoft auf einen externen service oder datenbank zu...
		List<Person> personen = new ArrayList<Person>();
		personen.add(new Person("Andreas", "Radauer", false));
		personen.add(new Person("Tesi", "Tester", true));
		personen.add(new Person("Asdf", "Jklö", false));
		nameTableModel.setData(personen);
	}
}
```

sollte funktionieren...


----------



## ARadauer (31. Dez 2012)

mit public void setValueAt(Object aValue, int rowIndex, int columnIndex)
kann man dann noch änderungen in seine liste schreiben, eventuell noch ein Set mit den nummern der geänderten zeilen und dann kann man bei einem speichnern schön auslesen was sich geändert hat...


----------



## infboy (2. Jan 2013)

ich möchte, dass in der Spalte "Verheiratet?" eine Checkbox angezeigt wird! in diesem Fall steht aber dort nur True und False! 
Wie kann man das? Das sollte ja eigentlich mit Hilfe des NameWindowTableModel gesetzt werden oder nicht? ???:L


----------



## SlaterB (2. Jan 2013)

jtable jcheckbox in eine Suchmaschine eintippen,
wenn auch vielleicht als erster Link inzwischen ein anderer Forum-Thread hier aufgeführt ist, der auch nur auf Suchmaschinen verweist,
http://www.java-forum.org/awt-swing-javafx-swt/116136-jcheckbox-jtable.html
aber mit solcher Meta-Wiederholung ist zu leben


----------



## infboy (4. Jan 2013)

danke an alle!

jetzt klappts!

doofer fehlr von mir.
statt Boolean.class hatte ich da boolean.class! und es ging nicht und es ging nicht!


----------

