# JTable und Datenbank



## T1M (29. Jun 2005)

Hi,
ich hab ne JTable, wo ich hart sachen reingeschrieben hab.
nun schreib ich gerad ne schnittstelle für ne datenbank, wo über eine abfrage die werte in meine tabelle sollen.
wie bekomm ich das hin? also, was muß ich der tabelle sagen, damit da die werte der abfrage reinkommen?
verwirrend? - find ich auch! :wink: 
Danke,
   T1M


----------



## AlArenal (29. Jun 2005)

Du schnappstst dir ein TableModel und schmeißt da deine DB-Daten rein, anschließend machst du ein JTable#setModel(TreeModel model) - fertig.


----------



## T1M (29. Jun 2005)

also, ich arbeite mit nem DefaultTableModel.
und welche datenbankdaten sollen da rein? die abfragen etc.? das geht leider net, die müssen!!! in ne andere klasse.


----------



## Roar (29. Jun 2005)

T1M hat gesagt.:
			
		

> Du schnappstst dir ein TableModel und schmeißt da deine DB-Daten rein, anschließend machst du ein JTable#setModel(TreeModel model) - fertig.


seit wann kann man denn einer JTable ein TreeModel geben


----------



## T1M (29. Jun 2005)

also, ums mal zu verdeutlichen:

```
String[] columnNames = {"Station", "Name"};

Object[][] data =
    {
    		{
    			"FW1", "Testname"
                },
                {
    			"FW1", "Name"
                },
                {
                            ...
                }
     };
```
so (hier vereinfacht) siehts bisher aus.
jetzt muß ich doch in Object[][] data = ... das datenbankzeug reinbekommen? oder muß ich das ersetzen?

Hilfe!
   T1M


----------



## AlArenal (29. Jun 2005)

@roar: 
Oh, war ein Vertipper.. gemeint war natürlich ein TableModel.

@t1m:



> also, ich arbeite mit nem DefaultTableModel.
> und welche datenbankdaten sollen da rein? die abfragen etc.? das geht leider net, die müssen!!! in ne andere klasse. icon_sad.gif



Watt? Nein, in das TableModel sollen natürlich die Daten aus deinen Abfragen rein, die du brauchst. 
Du machst deine Abfragen, schiebst die Daten in ein TableModel, machst für deine Table ein setModel() mit dem frisch befüllten TableModel und gut iss.


----------



## T1M (30. Jun 2005)

AlArenal hat gesagt.:
			
		

> ... schiebst die Daten in ein TableModel, ...


und eben das ist mein problem!

So schaut mal ne abfrage beimir aus (vereinfacht):

```
public String getTable(KreissaalPat patient) //KreissaalPat is ne Klasse, in der die Variablen stehn
    {
    	String sql = "select Station, Name "+
    				 "from Kreissaaltafel";
    	
    	Statement query = null;
        ResultSet daten = null;
        int i = 0;
        try
		{
            query = db.createStatement();
            daten = query.executeQuery(sql);
            while (daten.next())
            {
            	patient.Station = daten.getString("Station");
            	patient.Name = daten.getString("Name");
 
            	i += i;  //Anzahl durchgänge der while-schleife
            }
        }
        catch(Exception e) 
        {
        	 i=0;
        };
        System.out.println("Anzahl = "+i);
        return ""+patient;
    }
```
wie bekomm ich das ergebnis der abfrage aus klasse B in das TableModel, welches  in klasse A steht?


----------



## Semerzo (30. Jun 2005)

Du könntest

```
public String getTable(KreissaalPat patient, DefaultTableModel model)
```
 machen. Dann hast du eine Referenz auf das TableModel in deiner Methode und kannst ganz normal darauf zugreifen. Dann könntest du aus der Methode auch einen "void"-Typ machen, zurückgeben muss sie nichts mehr.


----------



## Oni (30. Jun 2005)

ich weiss nicht ob ich das richtig verstanden habe, aber vielleicht hilf dir das:

```
public KreissaalPat[] table(KreissaalPat patient)

ArrayList<KreissaalPat> list = new ArrayList<KreissaalPat>();
while(daten.next())
{
  patient.Station = ...

  list.add(patient);
}

return list.toArray(new KreissaalPat[0]);
```


----------



## Guest (30. Jun 2005)

Wozu dann überhaupt die KreissaalPat Klasse?
Verwende entweder direkt ein CachedRowSet oder schreibe ein TableModel, 
das mit KreissaalPat-Objekten umgehen kann. Am besten eins, dass so 
allgemein gehalten ist, dass es wiederverwendet werden kann. 
Die Konvertiererei ist absolut unnötig.
z.B. TableModel, das mit Collection beliebiger Objekte umgehen kann und eine 
Beschreibung der anzuzeigenden Spalten enthält.


----------



## T1M (30. Jun 2005)

Anonymous hat gesagt.:
			
		

> Wozu dann überhaupt die KreissaalPat Klasse?


hmm, weiß net genau.   aber das soll halt so sein.
plöd is, das ich die db-klasse nicht neu schreibe, sondern eine bestehende erweiter, für mein prog. deswegen geht auch das 
	
	
	
	





```
public String getTable(KreissaalPat patient, DefaultTableModel model)
```
 net. denn die klasse DBFrids (die datenbankklasse) kennt kein DefaulttableModel.
und ein 'extends Tafel' (meine klasse, wo die tabelle drin is) geht au net. da steht scho 'extends Object'.
find das alles recht unverständlich, hatte erst ein semester java. und im grunde hab ich mir alles selber beigebracht :?


----------



## Guest (1. Jul 2005)

Hier eine einfache Lösung mit einem Model, dass mit Collections von beliebigen Objekten umgehen kann.

```
abstract class CollectionTableModel<E> extends AbstractTableModel {

  private ArrayList<E> data = new ArrayList<E>(512);

  public void setData(Collection<E> data) {
    this.data.clear();
    this.data.addAll(data);
    fireTableDataChanged();
  }

  public Collection<E> getData() {
    Collection<E>result = new ArrayList<E>(data.size());
    result.addAll(data);
    return result;
  }

  protected abstract Object getValueAt(E src, int column);

  public Object getValueAt(int row, int column) {
    return getValueAt(data.get(row), column);
  }

  protected abstract void setValueAt(E dst, int column, Object value);

  public void setValueAt(Object value, int row, int column) {
    setValueAt(data.get(row), column, value);
    fireTableRowsUpdated(row, row);
  }

  public int getRowCount() {
    return data.size();
  }
}
```
Für die Klasse KreissaalPat musst Du es wie folgt implementieren.
	
	
	
	





```
...
  CollectionTableModel<KreissaalPat> model = new CollectionTableModel<KreissaalPat>() {
    protected Object getValueAt(KreissaalPat src, int column) {
      return (column==0)?src.getStation():src.getName();
    }

    protected void setValueAt(KreissaalPat dst, int column, Object value) {
      if(column==0)
        dst.setStation((String)value);
      else
        dst.setName((String)value);
    }

    public int getColumnCount() {
      return 2;
    }

    public String getColumnName(int column) {
      return (column==0)?"Station":"Name";
    }
  };

  table.setModel(model);
  ...
```
Deine Methode zum Zugriff auf die Datenbank sollte ungefähr folgende Signatur haben

```
public Collection<KreissaalPat> getKreissaalPatienten();
```
Dann verwendest Du es wie folgt
	
	
	
	





```
CollectionTableModel<KreissaalPat> model = (CollectionTableModel<KreissaalPat>)table.getModel();
model.setData(getKreissaalPatienten());
```

Das TableModel kannst Du noch erweitern, um Zeilen einzufügen, zu löschen, zu sortieren etc.
Ich hoffe, das hilft.


----------



## T1M (1. Jul 2005)

krass! auf jeden fall mal ein dickes Danke! werd das mal versuchen.
hab meine table allerdings mit nem DefaultTableModel gemacht, da hats ja schon die methoden addRow und removeRow.
aber werds mal versuchen!


----------



## T1M (1. Jul 2005)

hmm, hab da noch n paar fragen ...
warum steht da z. B. '<E>'?
und muß man für 
	
	
	
	





```
abstract class CollectionTableModel<E> extends AbstractTableModel { ... }
```
 ne neue klasse öffnen, oder kann ich das in meiner klasse Tafel gleich ins panel klatschen?
du sagst, es könne mit beliebigen objecten umgehen. ich hab da n ColorTableCellRenderer der an die table n Object vom typ color übergibt. das brauch ich um zeilen einzufärben. geht das dann auch mit dem neuen?
sry, me noob!  
und was machst du um halb 5 uhr morgens am rechner?!   :wink:


----------



## Guest (1. Jul 2005)

T1M hat gesagt.:
			
		

> hmm, hab da noch n paar fragen ...
> warum steht da z. B. '<E>'?
> und muß man für
> 
> ...


<E> ist eine Art "Platzhalter". Es kommt von Generics. Neues Spielzeug in JDK 1.5.
Du kannst es nicht direkt verwenden, da die Klasse "abstract" ist. Also noch nicht vollständig implementiert.
Verwende den zweiten Codeausschnitt aus meiner letzten Antwort.


			
				T1M hat gesagt.:
			
		

> du sagst, es könne mit beliebigen objecten umgehen. ich hab da n ColorTableCellRenderer der an die table n Object vom typ color übergibt. das brauch ich um zeilen einzufärben. geht das dann auch mit dem neuen?


Wenn der Renderer korrekt implementiert ist, ja. Wenn es aber davon ausgeht, dass man ein spezielles
Model verwendet (DefaultTableModel ist ja eins), dann nicht.
Versuche es. Wenn ClassCastException kommt, dann sehen wir weiter. (kannst Du den Code aus dem Renderer zeigen?)


			
				T1M hat gesagt.:
			
		

> sry, me noob!


Was erwartest Du nach einem halben Jahr.  Keine Panik.


			
				T1M hat gesagt.:
			
		

> und was machst du um halb 5 uhr morgens am rechner?!   :wink:


Das frage ich mich auch. 
Das Gewitter hat mich geweckt, da habe ich den PC eingeschaltet und spiele hier 'ne Runde Klugscheißer.


----------



## T1M (1. Jul 2005)

oki, erstmal der code des renderers:

```
import javax.swing.table.*;
import java.awt.*;
import java.awt.Color;
import javax.swing.*;
import java.util.Arrays;

class ColorTableCellRenderer extends DefaultTableCellRenderer
{
  private boolean[][] isHighlighted;
  private String[] arr;
  
  public Component getTableCellRendererComponent(JTable table, Object value,
  												 boolean isSelected, boolean hasFocus,
												 int row, int column)
  {
    if (isHighlighted == null)
    {
    	isHighlighted = new boolean[table.getRowCount()][table.getColumnCount()];
    }

    super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    
    if (isHighlighted[row][column])
    {
    	setBackground(Color.RED);
    }
   
    else
    {
    	super.getTableCellRendererComponent(table, table.getValueAt(row, column),
    								  isSelected, hasFocus, row, column);
    	setBackground(table.getBackground());
    }
  
    return this;
  }

  public void setHighlighted(final int row, final int column, final boolean highlight)
  {
    isHighlighted[row][column] = highlight;  //um eine zelle zu färben
  }
  
  public void setHighlighted( final int row, final boolean highlight )
  { 
  	Arrays.fill( isHighlighted[row], highlight ); //um ganze zeile zu färben
  }
}
```

und so übergeb ich den an meine table aus der klasse Tafel:

```
model = new DefaultTableModel(data, columnNames);
        table = new JTable(model)
		{
	     public Class getColumnClass(int i)
	     {
	     	return Color.class;
	     }
	   };
```
des hab ich jetzt mal einkommentiert und da deinen code hingepackt. hab die ganzen <E>s gelöscht, doch jetzt sagt er mir: Collection cannot be resolved (or is not a valid type) for the parameter data of the method setData, bzw. getData.
also, wo genau soll dein code hin? anstelle meiner table?
und ich verwende java 1.4.2 und werd das auch nicht ändern können ...

Hmm, ich dacht mir schon das das mit der datenbankanbindung schwirig wird. allerdings dacht ich das die anbindung probleme bereiten würde, nicht die übergabe der werte ... Wie heißts so schön? programmieren lernt man nur durch programmieren! :roll:
Danke das du mir weiterhilfst!!!!


----------



## Guest (1. Jul 2005)

Mach' mal 

import java.util.*;

dann sind die Klassen Collection und ArrayList bekannt. 
Ändere auch die zwei Methoden aus dem zweiten Code-Ausschnitt in
	
	
	
	





```
...
    protected Object getValueAt(Object src, int column) { 
      KreissaalPat p = (KreissaalPat)src;
      return (column==0)?p.getStation():p.getName(); 
    } 

    protected void setValueAt(KreissaalPat dst, int column, Object value) { 
      KreissaalPat p = (KreissaalPat)dst;
      if(column==0) 
        p.setStation((String)value); 
      else 
        p.setName((String)value); 
    }
...
```


----------



## T1M (1. Jul 2005)

jojo datt.
hatte aber schon 
	
	
	
	





```
import java.util.ArrayList;
import java.util.Collections;
```
 angegeben, dachte das würde es auch tun...
nu sagt er aber bei

```
protected abstract Object getValueAt(E src, int column);
```
E cannot be resolved (or is not a valid type) for the parameter src of the method getValueAt
und bei getValueAT und setValueAt kommt des: The method getValueAt(int, int) in the type CollectionTableModel is not applicable for the arguments  (Object, int)
bzw.: The method setValueAt(Object, int, int) in the type CollectionTableModel is not applicable for the  arguments (Object, int, Object)
ich liste einfach mal weiter auf *nerv* :roll: 

```
return (column==0)?p.getStation():p.getName();
```
 The method getStation() is undefined for the type KreissaalPat und The method getName() is undefined for the type KreissaalPat
das gleiche bei setStation und setName.
Was is mit meinen ColorTabelRenderer? der dürfte ja dann nit funzen, da er ja extends DefaultTableCellRenderer hat, gell?


----------



## Guest (1. Jul 2005)

Der Renderer hat nichts mit dem TableModel zu tun.
Das mit den Methoden getName() und getStation() ist sicher nur ein Folgefehler.

Hier mal alles zusammen.

```
// Das hier in einer Datei (CollectionTableModel.java) getrennt speichern.
abstract class CollectionTableModel extends AbstractTableModel {

  private ArrayList data = new ArrayList(512);

  public void setData(Collection data) {
    this.data.clear();
    this.data.addAll(data);
    fireTableDataChanged();
  }

  public Collection getData() {
    Collection result = new ArrayList(data.size());
    result.addAll(data);
    return result;
  }

  protected abstract Object getValueAt(Object src, int column);

  public Object getValueAt(int row, int column) {
    return getValueAt(data.get(row), column);
  }

  protected abstract void setValueAt(Object dst, int column, Object value);

  public void setValueAt(Object value, int row, int column) {
    setValueAt(data.get(row), column, value);
    fireTableRowsUpdated(row, row);
  }

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

//----------------------------------------------------------------------------
// Das hier kommt dorthin, woi Du die Tabelle initialisierst

CollectionTableModel model = new CollectionTableModel() {

  protected Object getValueAt(Object src, int column) {
    KreissaalPat p = (KreissaalPat)src;
    return (column==0)?p.getStation():p.getName();
  }

  protected void setValueAt(Object dst, int column, Object value) {
    KreissaalPat p = (KreissaalPat)dst;
    if(column==0)
      p.setStation((String)value);
    else
      p.setName((String)value);
  }

  public int getColumnCount() {
    return 2;
  }

  public String getColumnName(int column) {
    return (column==0)?"Station":"Name";
  }

};

table = new JTable(model);
// hier Dein ausgefallener, bunter Renderer ;)
table.setDefaultRenderer(Object.class, new ColorTableCellRenderer());

//----------------------------------------------------------------------------
// dann irgendwo, wo Du die Daten liest.

CollectionTableModel m = (CollectionTableModel) table.getModel();
m.setData(getKreissaalPatienten());

//----------------------------------------------------------------------------
// ...und die Methode getKreissalPatienten()

public Collection getKreissalPatienten() {

  Collection list = new ArrayList(128);

  ... die Datenbankabfrage
  while(resultSet.next()) {

    KreissaalPat p = new KreissaalPat();
    p.setStation(resultSet.getString("Station"));
    p.setName(resultSet.getString("Name"));
    list.add(p);

  }

  ... ResultSet, Statement und Connection schliessen

  return list;
}
```

Hat das ganze irgendwas mit der KBV zu tun?  ???:L :bae:


----------



## T1M (1. Jul 2005)

Wow, THX!!!! werd mich da mal durchackern!
du meinst die Kassenärztliche Bundesvereinigung? ne, eher weniger ... bis goar nix!
ich mach gerad n praktikum in einer Frauenklinik ^^, und da soll ich ne Kreissaaltafel programmieren. da steht dann station, name, entbindungstermin, diagnose, therapie, etc. ... in der tabelle.
is scho nich ganz ohne, aber macht soweit spaß.
so, aber jetzt is erstmal wochenende! :lol: muß des halt bis mo warten ... :roll: 
Grüße, schönes we,
T1M


----------



## T1M (4. Jul 2005)

Anonymous hat gesagt.:
			
		

> Das mit den Methoden getName() und getStation() ist sicher nur ein Folgefehler.


Hi, hab das mal alles so gemacht, wie dus gesagt hast. und bis auf eine sache scheint auch alles zu klappen (jedenfalls zeigt eclipse keine fehler an ...)
und zwar bei sämtlichen getStation, getName, setStation und setName methoden gibt es folgende meldung:
The method setStation(String) is undefined for the type KreissaalPat

und das versteh ich net ganz:


			
				Anonymous hat gesagt.:
			
		

> // dann irgendwo, wo Du die Daten liest.
> 
> CollectionTableModel m = (CollectionTableModel) table.getModel();
> m.setData(getKreissaalPatienten());


wo ich welche daten lese?
Hoffe du bist da ...,
    Danke,
   T1M

edit: joa, is klar das er getName, etc. nicht kennt. in der Klasse KreissaalPat gibts die auch gar net, da kann er sie ja nicht kennen ...


----------

