# JTable strecken & d. Spalten Vorgeschr. Gr. geben



## taik84 (29. Juli 2005)

Servus Leutz

Ich bastele gerade an einem Programm, das größtenteils an & mit einem JTable arbeitet.
Hier ist ein kleiner Auszug daraus.

```
String columnNames[] = {bla bla bla bla bla bla bla bla bla bla};
String data[][] = new String[1][11];
JTable tab = new JTable(data,columnNames){
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return false;
    }
  };
JScrollPane overview = new JScrollPane(tab);
JPanel center = new JPanel();
public void bla(){
   main.setLayout(new BoxLayout(main, BoxLayout.X_AXIS));
   main.add(center);
   center.setLayout(new FlowLayout());
   center.add(overview);
}
```
Meine Fragen wären:
1. Wenn ich das Programm ausführe, dann zeigt sich die Tabelle in der Mitte zusammegeknirscht und breitet sich nicht auf das ganze Panel aus. Komisch. Wie kann ich es beheben?

Wie hier : http://edv.cs.tu-berlin.de/~tretner/hg_klein.JPG

2. Wie kann ich in der Tabelle die Veränderung der Anzahl der Zeilen relativ einfach realisieren? Muss ich jetzt eigene Klasse bauen? Ich würde es gerne so haben, dass man auf einen Button drückt, dann erscheint ein kleines Fenster, wo ich die Daten eingebe und OK drücke und daraufhin dieses Fenster sich schließt und in der Tabelle im Hauptfenster die neue Zeile mit den eingegeben Daten eingefügt wird.

3. Und wie kann ich vorgeben, dass die Spalten eine bestimte Zahl an Zeichen besitzt?

So weit bin ich schon:

```
import javax.swing.table.*;
public class MyTableModel extends DefaultTableModel {
  String columnNames[];
  public DepotTableModel(Object[][] data, String[] columnNames){
    super(data, columnNames);
    this.columnNames = new String[columnNames.length];
    this.columnNames = columnNames;
  }
  public String getColumnName(int index) {
    return columnNames[index];
  }
  public int getColumnCount() {
    return 11;
  }
  public int getRowCount() {
    return -1;
  }
  public Object getValueAt(int row, int col) {
    return -1;
  }
  public Class getColumnClass(int index){
    try {
        switch (index) {
          case 0:
            return Class.forName("java.lang.String");
          case 1:
            return Class.forName("java.lang.String");
          case 2:
            return Class.forName("java.lang.Integer");
          case 3:
            return Class.forName("java.lang.String");
          case 4:
            return Class.forName("java.lang.Double");
          case 5:
            return Class.forName("java.lang.Double");
          case 6:
            return Class.forName("java.lang.String");   //Datum
          case 7:
            return Class.forName("java.lang.Double");
          case 8:
            return Class.forName("java.lang.Double");
          case 9:
            return Class.forName("java.lang.Double");
          case 10:
            return Class.forName("java.lang.Double");
          default:
            return null;
        }
    } catch (Exception e) {
        return null;
      }

  }
}
```

Danke.

Gruß

Taik


----------



## Snape (31. Juli 2005)

taik84 hat gesagt.:
			
		

> Servus Leutz
> 1. Wenn ich das Programm ausführe, dann zeigt sich die Tabelle in der Mitte zusammegeknirscht und breitet sich nicht auf das ganze Panel aus. Komisch. Wie kann ich es beheben?



Indem Du das Layout richtig verwendest. Entweder in einem BorderLayout in die Position CENTER setzt oder im GridBagLayout die entsprechenden Constraints setzt - je nachdem, welches Layout Du verwendest. NullLayout und GridLayout eignen sich nicht wirklich gut...



> 2. Wie kann ich in der Tabelle die Veränderung der Anzahl der Zeilen relativ einfach realisieren? Muss ich jetzt eigene Klasse bauen? Ich würde es gerne so haben, dass man auf einen Button drückt, dann erscheint ein kleines Fenster, wo ich die Daten eingebe und OK drücke und daraufhin dieses Fenster sich schließt und in der Tabelle im Hauptfenster die neue Zeile mit den eingegeben Daten eingefügt wird.



Eine geeignete Implementierung der Methode getRowCount() ist dafür notwendig.
Einfach nur -1 zurückzugeben ist offensichtlich falsch.



> 3. Und wie kann ich vorgeben, dass die Spalten eine bestimte Zahl an Zeichen besitzt?



Meinst Du jetzt zur Eingabe? Dabei hilft die Verwendung eines Documents (bitte Suchfunktion benutzen).


----------



## taik84 (31. Juli 2005)

> Indem Du das Layout richtig verwendest. Entweder in einem BorderLayout in die Position CENTER setzt ...



Habe ich schon ausprobiert. Hat auch nicht funktioniert. Deswegen bin ich zu BoxLayout + FlowLayout übergegangen.



> Eine geeignete Implementierung der Methode getRowCount() ist dafür notwendig.
> Einfach nur -1 zurückzugeben ist offensichtlich falsch....



Ich gebe -1, weil ich nicht wirklich weiss wie ich es implementieren soll und der Compiler immer meckert, wenn ich gar nichts reinschreibe und um Fehler zumindest im Rest des QuellCodes zu finden, habe ich mich für return -1 entschieden ;-). Ich habe ein paar Beispiele im Internet gefunden, aber wenn ich nicht verstehe, was  da gemacht wird, kann ich es auch nicht auf meine Situation anpassen.

Könntet mir etwas hier helfen?



> Meinst Du jetzt zur Eingabe? Dabei hilft die Verwendung eines Documents (bitte Suchfunktion benutzen).



Nö. Ich meinte, dass die Spaltenbreite eine Bestimmte Zeichenzahl anzeigt (z.B. 7 Chars) und den Rest mit "..." abkürzt(z.B. "Nö. Ich...").


Gruß

Taik


----------



## Snape (31. Juli 2005)

taik84 hat gesagt.:
			
		

> Habe ich schon ausprobiert. Hat auch nicht funktioniert. Deswegen bin ich zu BoxLayout + FlowLayout übergegangen.



Klar, weil Du im TableModel immer -1 oder NULL zurück gibst, wie soll die Tabelle denn dann wohl aussehen?



> Ich gebe -1, weil ich nicht wirklich weiss wie ich es implementieren soll und der Compiler immer meckert, wenn ich gar nichts reinschreibe und um Fehler zumindest im Rest des QuellCodes zu finden, habe ich mich für return -1 entschieden ;-).



Das ist eher suboptimal. Wie soll sich Java denn vorstellen, was -1 Zeilen sind? 1 kann er zeichnen, 2, 3,... aber -1? Du kannst testweise mal 10 zurückgeben lassen, das funktioniert. Idealerweise ist der Rückgabewert eine Größe oder Länge des verwendeten Datenobjekts, auf welches bei getValueAt() zurückgegriffen wird. Mir scheint, Du hast von JTable und TableModel noch nicht viel verstanden, knie Dich bitte intensiv in das Thema hinein.



> Ich habe ein paar Beispiele im Internet gefunden, aber wenn ich nicht verstehe, was  da gemacht wird, kann ich es auch nicht auf meine Situation anpassen.
> 
> Könntet mir etwas hier helfen?



Du musst schon konkret zeigen, an welchen Stellen es (vom Verständnis?) klemmt.



> Nö. Ich meinte, dass die Spaltenbreite eine Bestimmte Zeichenzahl anzeigt (z.B. 7 Chars) und den Rest mit "..." abkürzt(z.B. "Nö. Ich...").
> 
> Gruß
> 
> Taik



Das geschieht normalerweise automatisch, wenn der beinhaltete Text länger ist, als dargestellt werden kann.


----------



## taik84 (31. Juli 2005)

```
JTable tab = new JTable(data,columnNames){
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return false;
    }
  };
```
Hier kannst Du sehen, dass ich noch nichts von meinem neuen Modell verwendet habe. ;-)
Das ist das Standart, was von Java schon vorgegebn ist. ;-) Und trotzdem funktioniert es nicht mit dem Anzeigen auf die volle größe.


----------



## Snape (31. Juli 2005)

Dann sieh zu, dass Du in data und columnNames Inhalte hinein bekommst.

String columnNames[] = {bla bla bla bla bla bla bla bla bla bla};
String data[][] = new String[1][11];

reicht dafür nicht aus.
Mir erscheint dieser Thread als recht wenig ergiebig. Du hast Dich weder mit JTable noch mit dem TableModel halbwegs beschäftigt und präsentierst hier immer nur Codestückwerk ohne Zusammenhang.


----------



## taik84 (31. Juli 2005)

Hier ist die Hilfe, die ich verwendet habe:
https://www.tu-chemnitz.de/wirtschaft/wi1/lehre/2005_ss/wi_pr3/java2/jtable.htm

Gruß

Taik


----------



## taik84 (31. Juli 2005)

Ja es tut mir auch leid, dass ich zu viel Code verwendet habe. Aber es sich lange keiner gemeldet, deswegen dachte ich, dass ich zu wenig an Information gegeben habe. Also habe ich mein Beitrag ergänzt. Wenn ich irgendwas gefunden habe, habe ich dazugeschrieben. Dann weiter im Internet geuscht und weiter ausprobiert.

Taik


----------



## taik84 (31. Juli 2005)

```
String columnNames[] = {"Name","WKN","Stück","Währung","Devisenkurs","Einstandskurs","Datum","Kurs","Kapital","Veränderung","Anteil"};
  String data[][] = new String[1][11];
  JTable tab = new JTable(data,columnNames){
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return false;
    }
  };
  JScrollPane overview = new JScrollPane(tab);
```

Das ist der wirklicher Code, der auch von mir verwendet wird.


----------



## Snape (31. Juli 2005)

taik84 hat gesagt.:
			
		

> ```
> String columnNames[] = {"Name","WKN","Stück","Währung","Devisenkurs","Einstandskurs","Datum","Kurs","Kapital","Veränderung","Anteil"};
> String data[][] = new String[1][11];
> JTable tab = new JTable(data,columnNames)
> ```



data enthält NICHTS. Lies bitte in einem Buch nach, wie Arrays initialisiert werden.


----------



## taik84 (1. August 2005)

Inhalten hineinbekommen?
Ist doch nicht schwer. Zumindest dachte ich mir. ;-)

```
String columnNames[] = {"Name","WKN","Stück","Währung","Devisenkurs","Einstandskurs","Datum","Kurs","Kapital","Veränderung","Anteil"};
  String data[][] = {{"bla","bla","bla","bla","bla","bla","bla","bla","bla","bla","bla"}};
  JTable tab = new JTable(data,columnNames){
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return false;
    }
  };
```
Oder meinst Du was anderes?

Taik


----------



## Snape (1. August 2005)

So in der Art, obgleich ein zweidimensionales Array syntaktisch etwas anders gefüllt wird...


----------



## taik84 (1. August 2005)

So wiet bin ich jetzt:
http://www.edv.cs.tu-berlin.de/~tretner/hg.jpg

Also ich kann aus der Datenbank in die Tabelle [1][11] reinschreiben.
Aber ich habe immer noch ein Problem die Tabelle dynamisch zuerweitern und zu zureduzieren.

Wünde mich über eine Hilfe freunen.

Danke.

Gruß

Taik


----------



## taik84 (2. August 2005)

So wie ich im Internet gelesen habe und falls ich alles richtig verstanden habe, komme ich um meinen eigenen TableModel nciht herum. Ich konnte rausfinden, dass ich folgende Funktionen implementieren muss:
Class getColumnClass( int columnIndex )
Liefert das allgemeinste Klassenobjekt, welches die Spalte beschreiben kann.
int getColumnCount()
Liefert die Anzahl Spalten.
String getColumnName( int columnIndex )
Gibt den Namen der Spalte columnIndex zurück.
int getRowCount()
Liefert die Anzahl der Zeilen.
Object getValueAt( int rowIndex, int columnIndex )
Gibt den Eintrag an der Stelle columnIndex und rowIndex zurück.
void setValueAt( Object aValue, int rowIndex, int columnIndex )
Setzt den Wert an die gegebene Stelle.
boolean isCellEditable( int rowIndex, int columnIndex )
Liefert true, wenn die Zelle an rowIndex und columnIndex editierbar ist.
void addTableModelListener( TableModelListener l )
Fügt einen Ereignisbehandler hinzu, der immer dann informiert wird, wenn Daten geändert werden.
void removeTableModelListener( TableModelListener l )
Entfernt den Ereignisbehandler.

Was ich immer noch nicht vorstellen kann, wie ich auf die einzelne Einträge zugreifen kann? Mit welchem Befehl sollte ich auf die i. Zeile zugreifen? Und wie kann ich die Zeile hinzufügen, wenn ich ein Array von Daten habe (zumindest denke ich, dass ich es habe). Ich dachte, dass Arrays eine vordefinierte Länge haben und lassen sich nur sehr schwer erwitern. Einziges was mir in den Sinn kommt, sind die Listen.

Gruß

Taik


----------



## Snape (2. August 2005)

taik84 hat gesagt.:
			
		

> So wie ich im Internet gelesen habe und falls ich alles richtig verstanden habe, komme ich um meinen eigenen TableModel nciht herum.


Genau.


> Ich konnte rausfinden, dass ich folgende Funktionen implementieren muss:
> Class getColumnClass( int columnIndex )


Muss nicht, kann. Ist dafür gut, Renderer und/oder Editor für verschiedene Spalten unterschiedlich zu setzen


> int getColumnCount()


Korrekt.


> String getColumnName( int columnIndex )


Korrekt.


> nt getRowCount()


Korrekt.


> Object getValueAt( int rowIndex, int columnIndex )


Korrekt.


> void setValueAt( Object aValue, int rowIndex, int columnIndex )


Korrekt.


> boolean isCellEditable( int rowIndex, int columnIndex )


Nicht nötig, aber kann implementiert werden.


> void addTableModelListener( TableModelListener l )


Nicht nötig.


> void removeTableModelListener( TableModelListener l )


Auch nicht nötig.



> Was ich immer noch nicht vorstellen kann, wie ich auf die einzelne Einträge zugreifen kann? Mit welchem Befehl sollte ich auf die i. Zeile zugreifen? Und wie kann ich die Zeile hinzufügen, wenn ich ein Array von Daten habe (zumindest denke ich, dass ich es habe). Ich dachte, dass Arrays eine vordefinierte Länge haben und lassen sich nur sehr schwer erwitern. Einziges was mir in den Sinn kommt, sind die Listen.
> 
> Gruß
> 
> Taik



Genau. Wenn Du veränderbare Daten, vor allem Zeilen haben möchtest, muss ein dynamisches Konstrukt her. Also eine ArrayList oder ein Vector. Je nachdem, ob es threadsicher oder schnell sein soll.
BTW es geht auch - ist aber nicht meine Art der Programmierung - via addTableRow oder addRow, der Tabelle einen neuen Datensatz hinzuzufügen. Die persönlichen Anpassungen dabei sind aber begrenzt.


----------



## taik84 (3. August 2005)

Eine kleine Verständnissfrage:

In der MyTableModel muss doch irgend ein Verweis auf die Daten in der Tabelle sich finden, oder?

Wie solle ich es machen? Bei der Deklaration einfach oben eine neue Variable einfügen?

```
...
Object[][] data;
String[] colName;
...
public MyTableModel(Object[][] data,String[] colName){
    super(data,colName);
    this.data=data;
    this.colName=colName;
}
```

Aber dann speichere ich doch die Daten doppelt, oder?
Oder ist es vielleicht besser eigene Liste aufzubauen? Nimmt sie viel Speicher in Anspruch bei max 200 einträgen?
Was ist auch für ältere Computer besser?

Danke.

Gruß

Taik


----------



## Snape (3. August 2005)

taik84 hat gesagt.:
			
		

> Eine kleine Verständnissfrage:
> 
> In der MyTableModel muss doch irgend ein Verweis auf die Daten in der Tabelle sich finden, oder?


Genau.


> Wie solle ich es machen? Bei der Deklaration einfach oben eine neue Variable einfügen?


Jo.


> Aber dann speichere ich doch die Daten doppelt, oder?


Dann leg sie halt erst im TabelModel an. 


> Oder ist es vielleicht besser eigene Liste aufzubauen?


Sobald Du die Daten dynamisch halten möchtest, also Zeilen hinzufügen, löschen usw., wirst Du natürlich Probleme mit Arrays bekommen. Deshalb ist es üblich, mit Listen zu Arbeiten. Jeder Listeneintrag enthält dann quasi eine Zeile.


> Nimmt sie viel Speicher in Anspruch bei max 200 einträgen?
> Was ist auch für ältere Computer besser?
> 
> Danke.
> ...



Darum mach Dir mal keine Gedanken.


----------



## taik84 (6. August 2005)

Hallo

Ich suche gerade nach einem BeispielCode für TableModel, das mit veränderlichen Daten arbeitet.

Ich habe: TableModel
              Listen-Klasse
              ListenElement-Klasse
              Hauptfenster-Klasse
TableModel greift auf die Liste und fügt hinzu und löscht die LstenElemente der Liste. Liste ist als Doppeltverkettete Liste mit referenzen auf das erste, letzte und ein Element dazwischen.

Danke

Gruß

Taik


----------



## taik84 (6. August 2005)

Eine Verständnissfrage:

Wenn ich die Daten in der Liste, die innerhalb der TableModel erzeugt wird, verändere, was geschiet dann?

Ich habe folgendes gemerkt: Wenn ich die oben erwähnte Liste mit hilfe einer Prozedur, die sich in TableModel-Klasse befindet, aber im Grunde genommen nur auf die Listen-Prozedur zugreift, die alle ListenElemente in der Liste löscht, taucht immer ein Fehler auf:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
 at Kaufliste.goToPosition(Kaufliste.java:59)
 at DepotTableModel.getValueAt(DepotTableModel.java:32)
 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.paintWithOffscreenBuffer(Unknown Source)
 at javax.swing.JComponent.paintDoubleBuffered(Unknown Source)
 at javax.swing.JComponent._paintImmediately(Unknown Source)
 at javax.swing.JComponent.paintImmediately(Unknown Source)
 at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
 at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
 at java.awt.event.InvocationEvent.dispatch(Unknown Source)
 at java.awt.EventQueue.dispatchEvent(Unknown Source)
 at java.awt.EventDispatchThread.pumpOneEventForHierarchy(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)

Danke für die HIlfe.

Gruß

Taik


----------



## taik84 (6. August 2005)

Ach und noch eine Frage:
Wenn ich versuche bevor ich ein Wert zurückgebe irgendwas auszurechnen, gibt es ein Fehler.

```
...
case 6:
   GregorianCalendar hlp = data.goToPosition(row).getDate(); //GregorianCalendar
   return new String(hlp.MONTH+"/"+hlp.DAY_OF_MONTH+"/"+hlp.YEAR);
...
```
Auf dieser weise gibt es keinen Fehler, aber ich bekomme nur den Klassenverweis:

```
...
case 6:
   return data.goToPosition(row).getDate();
...
```

Danke

Gruß

Taik


----------



## Snape (7. August 2005)

Sorry, ich mag jetzt hier keine Tabellengrundlagen erklären. Schau bitte in der Java Insel und/oder im Handbuch der Javaprogrammierung nach. Oder warte und hoffe auf ein Beispiel von Tom, falls er dazu Lust und Zeit haben sollte. Ich denke derweil darüber nach, ein Tutorial darüber zu schreiben.
Obwohl, wenn ich das hier sehe http://www.java-forum.org/de/viewtopic.php?t=5321 steht da schon eine Menge drin.


----------

