# JTable erstellen, um einen Bestand zu pflegen



## birdy (27. Dez 2016)

Hallo zusammen!
Ich stehe vor folgender Aufgabe:
ich möchte gerne (als Teil meiner Semesterabgabe, deswegen hier unter Hausaufgaben) eine Tabelle erzeugen, die Daten eines Vogelbestandes beinhaltet. Meine Java-Kenntnisse belaufen sich zur Zeit auf ungefähr Kapitel 13 von dem Buch "Java von Kopf bis Fuß", nur so nebenbei erwähnt. Durch das Buch und unglaublich lange Recherchen im Internet habe ich nun verstanden, wie GUI funktioniert und wie ich zumindest im Ansatz eine eigene Tabelle erzeugen kann. Ich hab auch hier im Forum viele Sachen gefunden, allerdings helfen die mir nur bedingt weiter, und vielversprechende Links wurden scheinbar schon rausgenommen 

Jedenfalls, in diese Tabelle soll ein Benutzer von außen dazu in der Lage sein, einen neuen Vogel hinzuzufügen und Angaben über Name, Geschlecht, Geburtsdatum etc. machen können und man soll nach einem Vogel suchen können. Ich hab das bis jetzt über ein DefaultTableModel versucht (wirklich nur versucht), aber es hapert besonders dabei, wenn ich einen Button "Vogel hinzufügen" damit belegen möchte, dass der Benutzer aufgefordert wird, die ganzen Angaben zu machen und diese dann als neue Zeile zu speichern.

Das mal so als Anfang. Mir ist auch eingefallen, dass man das Ganze ja am besten auch irgendwo / irgendwie speichern können sollte, damit nicht alles an Daten wieder weg ist, kann man sowas denn auch mit einer Tabelle verknüpfen? ...

Ich erwarte hier auch keine vorgefertigten Codes oder was auch immer, ich suche besonders nach einem Ansatz, wie ich das ganze am besten angehen könnte. 

Vielen Dank schonmal 
 - Bea


----------



## Libentis (27. Dez 2016)

Ich habe selber nur Grundlegende Kentnisse in GUI-Programmierung (Ich weiß was es ist und wie ich z.B. einen Taschenrechner damit hinkriegen könnte, aber viel mehr auch nicht). Sowas scheint doch das Richtige für dich zu sein: http://stackoverflow.com/questions/3549206/how-to-add-row-in-jtable
Also wie du schon versucht hast per DefaultTableModel und dann einfach einen Button hinzufügen der die Eingabe durch den User ermöglicht. Woran scheitert es denn?

Speichern kannste das Ganze als Textdatei. Ich würde dann zum Beispiel einfach beim Start dem Nutzer ermöglichen eine Datei auszuwählen oder standardmäßig eine aus einem Verzeichnis laden.


----------



## birdy (27. Dez 2016)

Genau, also sowas kriege ich auch hin. Es soll sich quasi für den Benutzer dann ein Feld oder sowas öffnen, wo er dann mit "Gib den Namen des Vogels ein:" aufgefordert wird, die Angaben zu machen, aber für jede Spalte halt einzeln, und mit Enter oder einem Klick auf einen Button in diesem Feld soll das Programm dann zur nächsten Spalte übergehen.

ok, das mit der Textdatei ist schonmal gut zu wissen, danke


----------



## Libentis (27. Dez 2016)

Warum denn für jede Spalte einzeln? Ich stelle es mir ziemlich vor immer wieder Fensterchen aufgeploppt zu kriegen bis ich endlich alle Informationen eingegeben...
Ginge nicht was in Richtung
     Name: Textfeld
     Größe: 
     Weitere Eigenschaften
Das ließe sich ja auch recht fix zusammenbasteln und wäre für den Nutzer bestimmt schöner. Dann kannst du die Daten einfach in deine DB schreiben. Die Textfelder können ja auch ruhig leer bleiben, dann steht da halt ein leerer String für z.B. Größe. Solltest nur evtl. darauf achten, dass da sonst sinnvolle Sachen drinstehen (Größe: "Foo" wäre z.B. wenig sinnvoll, da sollten schon Zahlen stehen)


----------



## birdy (27. Dez 2016)

da hast du wohl Recht 
also meinst du das so, dass wenn man auf den Button "Vogel hinzufügen" klickt, dass dann einfach eine neue Zeile generiert wird und man dann quasi wie bei Word oder Excel in das Feld reinklickt und da dann seine Angaben macht?


----------



## Libentis (27. Dez 2016)

Wäre auch schön, ja.
Aber mein Gedanke war eher, dass dann einfach ein Fenster aufploppt mit allen Eigenschaften und Textfelder daneben.
Sowas:
----------------------------------------
| Name: [Das hier ist ein Textfeld]  |
| Größe: [Das hier ist ein Textfeld]  |
| Anderes Zeug                              |
|                                                  |
| Bestätigen           Abbrechen        |
-----------------------------------------
Aber deins ist wahrscheinlich einfacher 

P.S.: Solltest allerdings nicht zuviel Wert auf meine Meinung legen, bin auch nur ein einfacher Informatik student

Edit:
Das Fenster sieht leider nicht so schön aus, wenn ich es poste. Aber du weißt was ich meine.


----------



## birdy (27. Dez 2016)

ich glaube deine Meinung ist trotzdem qualifizierter als meine  ich hab Informatik nämlich nur so nebenbei, nicht so richtig als Hauptfach 

dann werd ich morgen mal schauen, ob ich das so hinkriege


----------



## Libentis (27. Dez 2016)

Dann vielleicht 

Viel Glück, kannst zu Not ja nochmal fragen  Kleiner Tipp am Rande zum Speichern, was das Speichern und Einlesen einfacher machen könnte: Du könntest den XMLEncoder / XMLDecoder nutzen um einfach eine xml Datei zu erstellen die deine Daten hält. Habe mal ein Beispiel rausgekramt.


```
Map<Number, Student> studenten = new HashMap<>();
public void laden() {
        try {
            XMLDecoder d = new XMLDecoder(
                                new FileInputStream("personen.xml"));
            studenten.clear();
            studenten = (HashMap<Number, Student>) d.readObject();
            d.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Verwaltung.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void speichern() {
        try {
            XMLEncoder e = new XMLEncoder(
                            new FileOutputStream("personen.xml")
                    );
            e.writeObject(studenten);
            e.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Verwaltung.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
```


----------



## birdy (27. Dez 2016)

ich werd auf jeden Fall drauf zurückgreifen, danke 

und danke auch für das Beispiel, werd ich bestimmt gebrauchen können, wenn ich dann irgendwann mal soweit bin


----------



## birdy (28. Dez 2016)

jaa, also das mit der Tabelle klappt schonmal ein Stück weit besser 
den "Hinzufügen"-Button konnte ich auch richtig belegen, nur das klappt noch nicht so ganz, dass mir auch der zweite Button "Entfernen" direkt unter diesem Button angezeigt wird 
einmal hab ich das irgendwie hingekriegt, aber da waren die beiden Buttons dann nicht mittig unter der Tabelle, sondern ganz links am Rand.

Und ich kriege das noch nicht hin, dass die Tabelle so groß angezeigt wird, wie sie wirklich ist, und nicht die ganzen Spalten zusammenquetscht. Wenn ich da die Pixelangaben direkt eingebe, tut sich da nicht wirklich was ...


----------



## birdy (28. Dez 2016)

ok, also das Problem mit dem Buttons zentrieren hab ich in den Griff bekommen


----------



## Libentis (28. Dez 2016)

Top 
Liegt vermutlich am gewählten Layout. Kriegste wohl noch hin 
https://docs.oracle.com/javase/tutorial/uiswing/layout/problems.html

Aus Jucks und Dollerei habe ich mich da auch mal dran versucht. Ist jetzt eher so hingeklatscht und nicht unbedingt die reine Lehre. Vorallem das mittige Positionieren der Buttons rechts...In dem oberen Feld könnte man dann aber Fehler anzeigen. Diese müssten auch noch abgefangen werden. Sprich Eingaben kontrollieren und sowas.



Spoiler: Code:





```
package tabelle;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;

public class Tabelle extends JFrame {
 
    private static JPanel     panel;
    private static JPanel     eastSubPanel;
    private static JTable     table;
    private static JButton    add;
    private static JButton    addRow;
    private static JButton    remove;
    private static JLabel     sucheL;
    private static JTextField sucheT;
    private static DefaultTableModel dtm;
    private static TableRowSorter<DefaultTableModel> rowSorter;
 
    Tabelle() {
        panel    = new JPanel();
        eastSubPanel = new JPanel();
        add      = new JButton("Add");
        addRow   = new JButton("addRow");
        remove   = new JButton("remove");
        sucheL   = new JLabel("Suche: ");
        sucheT   = new JTextField();
    
        panel.setLayout(new BorderLayout());
        eastSubPanel.setLayout(new BoxLayout(eastSubPanel, BoxLayout.Y_AXIS));
    
        //Quick and dirty fix um das in die Mitte zu kriegen
        JTextField help = new JTextField();
        help.setEditable(false);
        // Ende schlechter Fix
    
        eastSubPanel.add(help);
        eastSubPanel.add(add);
        eastSubPanel.add(addRow);
        eastSubPanel.add(remove);
        eastSubPanel.add(sucheL);
        eastSubPanel.add(sucheT);
        eastSubPanel.setSize(100, HEIGHT);
        eastSubPanel.setPreferredSize(new Dimension(100, HEIGHT));
    
        add.setAlignmentX(CENTER_ALIGNMENT);
        addRow.setAlignmentX(CENTER_ALIGNMENT);
        remove.setAlignmentX(CENTER_ALIGNMENT);
        panel.add(eastSubPanel, BorderLayout.EAST);
    
        erzeugeTabelle();
        addListener();
    
        add(panel);
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        pack();
        setVisible(true);
    }
 
 
 
    private static void erzeugeTabelle() {
        String[][] rowData = {
            { "Japan", "245" }, { "USA", "240" }, { "Italien", "220" },
            { "Spanien", "217" }, {"Türkei", "215"} ,{ "England", "214" },
            { "Frankreich", "190" }, {"Griechenland", "185" },
            { "Deutschland", "180" }, {"Portugal", "170" }
        };
    
        String[] columnNames =  {"Zeile", "Land", "Durchschnittliche Fernsehdauer pro Tag in Minuten" };
        dtm = new DefaultTableModel(columnNames, 0) {
            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                boolean[] canEdit = {false, true, true};
                return canEdit[columnIndex];
            }};
        table = new JTable(dtm);
        rowSorter = new TableRowSorter<>(dtm);
        table.setRowSorter(rowSorter);
    
        DefaultTableCellRenderer cr = new DefaultTableCellRenderer();
        cr.setHorizontalAlignment(JLabel.CENTER);
    
        for(int i=0; i<rowData.length; i++) {
            dtm.addRow(new Object[]{i+1, rowData[i][0], rowData[i][1]});
        };
        for(int i=0; i<table.getColumnCount(); i++) {
            table.getColumnModel().getColumn(i).setCellRenderer(cr);
        }
        panel.add(new JScrollPane(table), BorderLayout.CENTER);
    }
 
    private static void addListener() {
        add.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Test");
                JFrame fenster    = new JFrame();
                JPanel panel      = new JPanel();
                JTextField land   = new JTextField();
                JTextField dauer  = new JTextField();
                GridLayout layout = new GridLayout(3, 1);
                JButton submit    = new JButton("Submit");
                panel.setLayout(layout);
                panel.add(new JLabel("Land: "));
                panel.add(land);
                panel.add(new JLabel("Dauer: "));
                panel.add(dauer);
                panel.add(submit);
                submit.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        zeileHinzufuegen(land.getText(), Integer.parseInt(dauer.getText()));
                        fenster.dispose();
                    }
                });
                fenster.add(panel);
                fenster.setLocation(panel.getX()+panel.getWidth()/2, panel.getY()+panel.getHeight()/2);
                fenster.pack();
                fenster.setVisible(true);
            }
        });
    
        addRow.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                zeileHinzufuegen("Bitte Namen eintragen", -1);
            }
        });
    
        remove.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int row = Integer.parseInt(JOptionPane.showInputDialog(null, "Welche Zeile soll gelöscht werden?", "1"))-1;
                dtm.removeRow(row);
                for(int i=row; i<dtm.getRowCount(); i++)
                    dtm.setValueAt(i+1, i, 0);
            }
        });
    
        sucheT.getDocument().addDocumentListener(new DocumentListener() {
        
            /*
            (?i) case-insensitive
            (?-i) case sensitive
            Die 1 nach dem Komma bedeutet: Nur in der 1. Spalte suchen, wobei Indezierung bei 0 beginnt
            */
            @Override
            public void insertUpdate(DocumentEvent e) {
                String text = sucheT.getText();
                if(text.trim().length() == 0)
                    rowSorter.setRowFilter(null);
                else
                    rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                String text = sucheT.getText();
                if(text.trim().length() == 0)
                    rowSorter.setRowFilter(null);
                else
                    rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
            }
        });
    
    }
 
    public static void zeileHinzufuegen(String land, int dauer) {
        dtm.addRow(new Object[] {dtm.getRowCount()+1, land, dauer});
    }
}
```



Das Ganze sieht bei mir dann so aus. Ist jetzt nicht extrem schön, aber geht 

Nachtrag: 
Na dann^^
Wie hast du die Tabelle denn deinem Panel zugefügt?


----------



## birdy (28. Dez 2016)

oh wow, ich hoffe ich blick da durch, nach dem ersten Blick drauf ist das ja doch schon ein klein wenig fortgeschrittener als das was ich hier fabriziere  darf ich fragen, wie lange du dafür gebraucht hast?


----------



## birdy (28. Dez 2016)

um deinen Nachtrag zu beantworten: ich versuche jetzt mal so fachmännisch wie möglich darauf zu antworten 

ich habe die Tabelle in ein eigenes Panel gepackt und das dann dem Frame zugefügt, das gleiche hab ich auch mit den beiden Buttons gemacht. Es hat auf jeden Fall funktioniert, und mit setPrefferedSize hat jetzt alles auch seine richtige Größe


----------



## Libentis (28. Dez 2016)

Nicht so lange. 1,5 bis zwei Stunden. Vieles ist aber auch zusammengegoogled.
Wie man eine Tabelle benutzt: http://openbook.rheinwerk-verlag.de...19_019.htm#mj4d8b3bc0b550304f97713fa1788ff0f6
Suchen: http://stackoverflow.com/questions/22066387/how-to-search-an-element-in-a-jtable-java
Man muss das Rad ja nicht neu erfinden 
Der Rest ist ja nur noch Buttons hinzufügen und sehen, dass die an einer vernünftigen Position stehen.
Sieht wegen diesem GUI Zeug nur nach viel aus.
Zeig doch mal deins, wie es aussieht bist du jetzt fertig 

P.S.: Du solltest die Tabelle in eine JScrollBar setzen
panel.add(new JScrollPane(table));
Sonst könntest du nachher zuviele Einträge haben und man sieht die Hälfte nicht.


----------



## birdy (28. Dez 2016)

ooooh das ist so frustrierend, ich such mir das ja auch quasi alles raus und ich sitze schon seit Tagen hier dran, bis mal ein Teilerfolg eintritt 

ich klatsch meinen bisherigen Code hier mal rein, bitte nicht schimpfen weil alles in der main steht und so, da kümmer ich mich drum, wenn alles fertig ist 


```
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Dimension;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JPanel;
import javax.swing.table.*;

import java.util.Vector;

public class Tabelle
{
   public static void main( String[] args )
   {
       DefaultTableModel model = new DefaultTableModel();
  
       //Spalten anlegen
       model.addColumn("Name");
       model.addColumn("Geschlecht");
       model.addColumn("Geburtsdatum");
       model.addColumn("Zuchtform");
       model.addColumn("Farbschlag");
       model.addColumn("chronische Erkrankungen");
       model.addColumn("Lieblingsfutter");
    
       JTable tabelle = new JTable(model);
    
       JFrame frame = new JFrame();
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.setPreferredSize(new Dimension(1300, 500));
       frame.setMinimumSize(new Dimension(1300, 500));
    
    
       JPanel panelTabelle = new JPanel();
       panelTabelle.setAlignmentX(Component.CENTER_ALIGNMENT);
       panelTabelle.setLayout(new BoxLayout(panelTabelle, BoxLayout.Y_AXIS));
    
       panelTabelle.add(tabelle);
       panelTabelle.add(new JScrollPane(tabelle));
    
       JPanel panelButtons = new JPanel();
       panelButtons.setLayout(new BoxLayout(panelButtons, BoxLayout.Y_AXIS));
   
       //Button "Wellensittich hinzufügen" erstellen
       JButton hinzufügen = new JButton("Wellensittich hinzufügen");
       hinzufügen.addActionListener(new ActionListener()
               {
                       public void actionPerformed(ActionEvent e)
                       {
                           Vector vektor = new Vector();
                           vektor.add("");
                           vektor.add("");
                           vektor.add("");
                           vektor.add("");
                           vektor.add("");
                           vektor.add("");
                           vektor.add("");
                        
                           model.addRow(vektor);
                       }
               });
       hinzufügen.setAlignmentX(Component.CENTER_ALIGNMENT);
       panelButtons.add(hinzufügen);
    
       //Button "Wellensittich entfernen" erstellen
       JButton entfernen = new JButton("Wellensittich entfernen");
       entfernen.addActionListener(new ActionListener()
       {
               public void actionPerformed(ActionEvent e)
               {
                   int ausgewählteZeile = tabelle.getSelectedRows().length;
                
                   for(int i=0; i < ausgewählteZeile; i++)
                   {
                       model.removeRow(tabelle.getSelectedRow());
                   }
               }
       });
      entfernen.setAlignmentX(Component.CENTER_ALIGNMENT);
      panelButtons.add(entfernen);
   
      frame.getContentPane().add(BorderLayout.CENTER, panelTabelle);
      frame.getContentPane().add(panelButtons, BorderLayout.SOUTH);
    
    
       frame.pack();
       frame.setVisible(true);
  
   }
}
```



achso, die beiden Buttons gefallen mir immer noch nicht so ganz, aber das sind kosmetische Sachen, ich bin froh, dass erstmal alles funktioniert 

noch ein achso:
ich denke auch dadran, so ein Fenster aufploppen zu lassen, wie das bei deinem Code ist, dass man nochmal gefragt wird, ob man den Vogel wirklich löschen will. und was ich auch cool fänd, wenn ich das hinkriegen könnte, die Spalte Zuchtform so zu programmieren, dass man da die Auswahl zwischen drei vorgefertigten Formen hat. Und ich möchte noch 2 weitere Tabellen erstellen, die alle über verschiedene Reiter im gleichen Fenster angeklickt werden können. also ich hab noch einiges vor


----------



## Libentis (28. Dez 2016)

Ich programmiere aber ziemlich sicher mehr als du  Am Anfang kam ich mit GUI garnicht klar. Erst nachdem wir das in der Uni mal gemacht haben habe ich es dann auch verstanden. Aber ich kennn das, da sind die Kollegen alle schon lange mit ner Aufgabe fertig und man selber sitzt da und sucht vergeblich seinen Fehler 
Außerdem finde ich deine GUI schöner als meine  Vorallem das Löschen finde ich schön gelöst.

Zu deinem zweitem Achso:
Fenster aufploppen lassen geht ziemlich schnell. Wenn dir das Design gefällt könntest du sogar mit JOPtionPane arbeiten, dann geht das sehr flott.
https://de.wikibooks.org/wiki/Java_...:_javax_swing_JOptionPane#Confirmation_Dialog
Ich habe keine Ahnung was du mit den 3 verschiedenen Auswahlmöglichkeiten meinst... 
Wenn du auch noch mit TabbedPane arbeiten willst tu dir selber einen Gefallen und knall das nicht alles in die Main. Da verlierst du irgendwann mit ziemlicher Sicherheit den Überblick (spreche aus Erfahrung).

Dann noch viel Glück^^
Zu wann muss das denn fertig sein?

P.S.: Denk immer ans Sichern deines bisherigen Codes! Nicht dass du da dran rumspielst und aufeinmal nichts mehr läuft


----------



## birdy (28. Dez 2016)

Ich finde das auch immer sehr erniedrigend wenn man in seiner Gruppe da sitzt und alle davon reden, wie weit die sind und was die da alles einbauen und ich versuche dann immer ganz cool nicht direkt in Panik auszubrechen 

danke für den Link, werd ich mir mal anschauen 
das mit den Auswahlmöglichkeiten hab ich grad schon hingekriegt, und die Buttons auch, schau mal, wenn du das hier nach dem Panel für die Tabelle noch zwischenschiebst:


```
//eigenes Panel für die Tabelle anlegen
       JPanel panelTabelle = new JPanel();
       panelTabelle.setAlignmentX(Component.CENTER_ALIGNMENT);
       panelTabelle.setLayout(new BoxLayout(panelTabelle, BoxLayout.Y_AXIS));
       panelTabelle.add(tabelle);
       panelTabelle.add(new JScrollPane(tabelle));
      
       //JComboBox für die Zuchtform erstellen
       JComboBox comboBox = new JComboBox();
       comboBox.addItem("Standard");
       comboBox.addItem("Halb-Standard");
       comboBox.addItem("Hansi-Bubi");
      
       //ComboBox in die 4. Spalte hinzufügen (3, weil 0 erster Index ist)
       TableCellEditor editor = new DefaultCellEditor(comboBox);
       tabelle.getColumnModel().getColumn(3).setCellEditor(editor);
      
      
       //eigenes Panel für die Buttons anlegen
       JPanel panelButtons = new JPanel();
       panelButtons.setLayout(new BoxLayout(panelButtons, BoxLayout.Y_AXIS));
```

Danke  ich hab noch gut zwei Wochen Zeit, ich hab jetzt auch noch ein paar Tage frei, ich denke, wenn ich mich jetzt jeden Tag dran setze und immer ein gutes Stück weit weiterkomme, sollte ich damit rechtzeitig fertig werden  zum Glück sind die anderen beiden Tabellen ähnlich aufgebaut  ich denke, ich werde für jede Tabelle eine eigene Klasse anlegen und die ganzen Sachen ordentlich in Methoden zusammenfassen und dann alles zusammen in der TappedPane zusammenführen ... irgendwie so 

Danke auch für's Erinnern, ich sollte wirklich mal 'ne Sicherung anwerfen, hab letztens auch erst eine andere Semesterabgabe fertig bekommen 

Und nochmal Danke für die Zeit, die du dir nimmst


----------



## Libentis (28. Dez 2016)

Ja...  Gott sei dank ist das Semester bald vorbei  Nachteil: Klausuren (bei mir in ca. 2,5 Wochen...). 

Kd. Aaah. Das ist gut. 
Erneut: Kd  Ich finde proggen macht mega Laune. Vorallem wenns um nichts geht sondern man einfach für sich proggt. Außer wenn es nicht so läuft wie man es gerne hätte und man einfach nicht auf den Fehler kommt 

In zwei Wochen sollte das machbar sein. Viel Spaß/Glück


----------



## birdy (28. Dez 2016)

jap, bei uns gehen die Klausuren auch in gut 3 Wochen los 

ja also ich muss sagen, solange man sichtbare Fortschritte macht, mache ich das auch irgendwie gerne, aber ich saß auch teilweise hier dran und hätte mein Notebook am liebsten irgendwo draußen ausgesetzt 

ich werd mal schauen, wie gut ich voran komme, bestimmt hackt es noch an der ein oder anderen Stelle, aaaaber ich kenn da jetzt wen, der da vielleicht helfen könnte   danke!


----------



## birdy (29. Dez 2016)

Hallöchen nochmal (ich fühl mich schon fast schlecht dabei, so oft was zu fragen  ),

ich hab noch eine Frage zu dem Beispiel was du wegen dem Speichern rausgesucht hattest, ich versteh das nicht so ganz mit dieser Map und wie die beiden Sachen da (Number und Student) zusammenhängen ... und was die Verwaltung zu bedeuten hat


----------



## Libentis (29. Dez 2016)

Nabend, 
kein Problem, das ist ein Forum und doch genau dafür da  
Ich denke du müsstest dich dafür erstmal mit der HashMap auseinander setzen. Zitat aus Java ist auch eine Insel :
"Die Klasse HashMap eignet sich ideal dazu, viele Elemente unsortiert zu speichern und sie über die Schlüssel schnell wieder verfügbar zu machen. Das interne Hashing-Verfahren ist schnell, eine Sortierung der Schlüssel nach einem gegebenen Kriterium aber nicht möglich."
Das Number sollte auch einfach durch ein Integer ersetzt werden können. Das ist der Schlüssel über den man die Elemente suchen kann. In meinem Fall nehme ich da einfach die Matrikelnummer eines Studenten, da diese ja eindeutig ist. Das dazu passende Element ist dementsprechend ein Student (eine meiner Klassen). Number muss übrigens eindeutig sein, das kann/darf logischerweise nicht doppelt vorkommen, da darüber ja der zugehörige Student gefunden wird. 
Mit Verwaltung meinst du wahrscheinlich das in dem catch? Das ist der standardmäßig von NetBeans generierte Catchblock. Verwaltung ist nur der Name der Klasse aus welcher der Code stammt. Also für den XMLEncoder / Decoder völlig irrelevant. 

Ich hoffe ich konnte es verständlich erklären


----------



## birdy (30. Dez 2016)

Hallo,

ja nein, so wirklich verstehe ich das nicht  das Zitat aus dem Buch hatte ich auch schon gelesen, aber ich komm da mit dem speichern und laden echt nicht weiter. Beim Speichern sehe ich wohl, dass er da irgendeine xml-Datei erstellt, aber was er da speichert kann ich beim besten Willen nicht erklären  

ich hab mich auch hieran orientiert: https://wiki.byte-welt.net/wiki/JTable_Inhalte_speichern

aber es klappt nicht


----------



## Libentis (30. Dez 2016)

Woran scheitert es denn? Magst nochmal posten was du bisher hast? 
Der XMLEncoder erzeugt nur eine textuelle Darstellung der Daten. Wie in dem Link von dir beschrieben muss das Objekt das geschrieben wird dafür einen parameterlosen Konstruktor und Getter/Setter haben. Viel mehr weiß ich leider auch nicht. Ich habs bisher nur einmal gebraucht und war froh, dass es auf Anhieb funktioniert hat


----------



## birdy (30. Dez 2016)

ich habe keine Ahnung, irgendwie klappt das nicht mit meinem model, dass so da reinzukriegen wie in dem Beispiel 

ich poste hier mal die Ausschnitte, die glaube ich relevant sind:


```
public class Tabelle_Bestand
{
   public static void main( String[] args )
   {
     
       DefaultTableModel model = new DefaultTableModel();
     
       //Tabelle erstellen
       JTable tabelle = new JTable(model);
       TableRowSorter<TableModel> rowSorter = new TableRowSorter<>(tabelle.getModel());
   
       //Spalten anlegen
       model.addColumn("Name");
       model.addColumn("Geschlecht");
       model.addColumn("Geburtsdatum");
       model.addColumn("Zuchtform");
       model.addColumn("Farbschlag");
       model.addColumn("chronische Erkrankungen");
       model.addColumn("Lieblingsfutter");
    
     
       //Frame erstellen und Größe zuweisen
       JFrame frame = new JFrame();
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.setPreferredSize(new Dimension(1300, 500));
       frame.setMinimumSize(new Dimension(1300, 500));
       frame.setTitle("Wellensittichbestand");
       frame.setLocationRelativeTo(null);
     
       //eigenes Panel für die Tabelle anlegen
       JPanel panelTabelle = new JPanel();
       panelTabelle.setAlignmentX(Component.CENTER_ALIGNMENT);
       panelTabelle.setLayout(new BoxLayout(panelTabelle, BoxLayout.Y_AXIS));
       panelTabelle.add(tabelle);
       panelTabelle.add(new JScrollPane(tabelle));


//hier ist der ganze Zwischenteil mit den anderen Buttons


//Button zum Speichern erstellen
      JButton speichern = new JButton("speichern");
      speichern.setMaximumSize(new Dimension(200, 100));
      speichern.addActionListener(new ActionListener()
       {
             public void actionPerformed(ActionEvent e)
             {
                 try
                 {
                     XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("wellensittiche.xml")));
                     encoder.writeObject(model);
                     encoder.close();
                 }
                 catch(IOException exception)
                 {
                     exception.printStackTrace();
                 }
             }
       });
      speichern.setAlignmentX(Component.CENTER_ALIGNMENT);
      panelButtons.add(speichern);
    
      //Abstand
      panelButtons.add(Box.createRigidArea(new Dimension (0, 10)));

      //Button zum Laden erstellen
      JButton laden = new JButton("laden");
      laden.setMaximumSize(new Dimension(200, 100));
      laden.addActionListener(new ActionListener()
       {
             public void actionPerformed(ActionEvent e)
             {
                 try
                 {
                     XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(new FileInputStream("wellensittiche.xml")));
                     model = (DefaultTableModel) decoder.readObject();
                     tabelle.setModel(model);
                     decoder.close();
                 }
                 catch(FileNotFoundException exception)
                 {
                     exception.printStackTrace();
                 }
             }
       });
      laden.setAlignmentX(Component.CENTER_ALIGNMENT);
      panelButtons.add(laden);
    
      //Abstand
      panelButtons.add(Box.createRigidArea(new Dimension (0, 10)));
    
    
      frame.getContentPane().add(BorderLayout.CENTER, panelTabelle);
      frame.getContentPane().add(panelButtons, BorderLayout.SOUTH);
     
     
       frame.pack();
       frame.setVisible(true);
   
   }
 
}
```


achso, ich habe übrigens auch eine Klasse "Wellensittch", bei der die ganzen Instanzvariablen drin stecken und jede Menge getter/setter-Methoden, um die alle zu setzen, aber das hatte ich geschrieben, bevor ich mit der Tabelle angefangen habe


----------



## Libentis (30. Dez 2016)

Auf den ersten Blick sieht es so aus, als würdest du versuchen direkt das DefaultTableModel in die Datei zu schreiben. Ganz so einfach geht das leider nicht, da dort ein Getter und Setter fehlt. Deswegen benutzt der Typ in deinem Link auch eine eigene Klasse, die das DefaultTableModel erweitert. Du hast jetzt m.E. Zwei Optionen:
1.:
Du erstellst dir einen vector<Wellensittich>. Wenn jetzt ein neuer Wellensittich hinzugefügt wird erstellst du einen Wellensittich und schiebst ihn in deinen Vektor, am Ende kannst du dann einfach den Vektor in die Datei scheiben  lassen (wie in meinem Beispiel). Da du ja nicht direkt alle Daten hast, da diese erst nach und nach eingegeben werden würde ich an deiner Stelle beim Speichern einfach einmal die Tabelle durchgehen und mir für jede Zeile alle Daten holen und daraus einen Wellensittich erstellen. Da reicht es ja diese als anonyme Objekte zu erstellen und direkt hinzuzufügen. 
Zweite Möglichkeit :
Genau wie in dem von dir geposteten Link eigene Klassen erstellen. 

Ich würde erstere Möglichkeit wählen, da diese für mich einfacher aussieht, allerdings ist die zweite deutlich eleganter. Einfach eine Tabelle reinschreiben ist halt viel schöner. Außerdem kannst du diese dann einfach wieder auslesen und hast die Tabelle. Bei der Ersten Möglichkeiten müsstest du quasi nochmal alles hinzufügen (ist aber nicht besonders viel Aufwand). 
Ich hoffe ich konnte es verständlich erklären. Ansonsten probiere ich es nachher nochmal


----------



## birdy (30. Dez 2016)

wow, danke für deine umfangreiche Antwort!

also einfacher klingt für mich am ansprechendsten 
so ganz verstehe ich das aber nicht. Ich denke mal, ich muss auf jeden Fall was an dem Button "hinzufügen" ändern, da arbeite ich ja schon mit dem Vektor. wenn ich den dann jetzt so ändere, dass er vom Typ her "Wellensittich" ist, dann funktioniert das mit dem vektor.add("") nicht mehr ...

und wenn ich das dann so wie in der 1. Option mache, funktioniert das mit dem Speichern und Laden so, wie du es in deinem gemacht hast?

das ist jetzt alles ein bisschen zu hoch für mich


----------



## Libentis (30. Dez 2016)

Ich kann gerade nicht nachgucken was genau du mit dem vektor machst (übrigens kein guter Name, Namen sollten sprechend sein). Wofür ist der nochmal da? 
Außerdem habe Ich da gerade sowieso ausversehen was verwechselt. Dir müsste eine ArrayList reichen, ich war bei vector aus c++, sry 
Du kannst entweder den Button ändern, dass wie bei mir ein Fenster aufploppt wo man alles eingeben muss, oder du gehst einfach deine Tabelle durch. Sprich:
Jede Zeile lesen und ein Objekt Wellensittich mit diesen Daten erstellen. Das Objekt schiebst du dann in deine Liste. Da du diese ja sonst nicht brauchst reicht es wenn das Objekt anonym ist(.push_back(new Wellensittich(hierstehendieganzendaten)))

Njein, nicht genau so. Ich hatte keine Tabelle, mir hat ne Map gereicht. Und die map habe ich dann in die Datei geschrieben. Wenn ich die Daten laden wollte habe ich die Datei einfach mit readObject gelesen und in meine map gespeichert. Ich denke aber, dass es genauso mit ner Liste gehen sollte. Wenn du die Daten gelesen hast kannst du sie einfach mit einer Schleife in die Tabelle übertragen, also kein Hexenwerk.


----------



## birdy (30. Dez 2016)

ok, dann werd ich das mit der ArrayList mal probieren, da das eh mein allererster Ansatz war, wird das schon schiefgehen 

ich probier mal rum, aber das wird ja dann doch länger dauern als ich dachte  erstmal versuche ich, dass das mit den Fenstern und der ArrayList so klappt, das ganze muss ja sicherlich verschachtelt werden, also in dem Button muss ja dann alles andere programmiert werden.

danke jedenfalls für deine Mühen!


----------



## Libentis (30. Dez 2016)

Wenn du deine bisherigen Ergebnisse nicht verwerfen möchtest lies doch einfach die Zeilen aus, das kann ja so schwer nicht sein. 
Hätte den Vorteil, dass du es beim editieren einfacher hast, da du die aktuellen Daten liest. Wenn du aber unbedingt ne Liste nehmen willst könntest du eine HashMap nehmen. Die Zeilennummer wäre dann der Schlüssel. Vorteil: einfaches finden des zu ändernden Elementes. Dann müsste man gucken wie man merkt, dass was editiert wurde. Du kannst ja die Felder direkt editieren. Ich hoffe, dass das nicht zuviel Input ist. Habe nur gedacht, dass ich es nochmal schnell erwähne, bevor du schon halb fertig bist


----------



## Libentis (30. Dez 2016)

Wenn du deine bisherigen Ergebnisse nicht verwerfen möchtest lies doch einfach die Zeilen aus, das kann ja so schwer nicht sein. 
Hätte den Vorteil, dass du es beim editieren einfacher hast, da du die aktuellen Daten liest. Wenn du aber unbedingt ne Liste nehmen willst könntest du eine HashMap nehmen. Die Zeilennummer wäre dann der Schlüssel. Vorteil: einfaches finden des zu ändernden Elementes. Dann müsste man gucken wie man merkt, dass was editiert wurde. Du kannst ja die Felder direkt editieren. Ich hoffe, dass das nicht zuviel Input ist. Habe nur gedacht, dass ich es nochmal schnell erwähne, bevor du schon halb fertig bist


----------



## birdy (30. Dez 2016)

oh keine Sorge, ich war grad eh erstmal am Schmollen und meinen Ergebnissen schonmal am Hinterherweinen  aber das ist eine gute Alternative, werd ich mal versuchen!


----------



## birdy (30. Dez 2016)

ich hab das Speichern & Laden endlich hinbekommen, ein Hoch auf die Tiefen des Internets 

das hier hat mir weitergeholfen: https://entwickler-forum.de/showthread.php/65227-JTable-Daten-serialisieren-lesen-und-schreiben

jetzt fehlt mir nur noch ein gemeinsames Panel mit verschiedenen Reitern, dann bin ich (hoffentlich) durch


----------



## Libentis (30. Dez 2016)

Top 
Ich habs gerade auch gemacht  
Falls es dich interessiert wie es bei mir aussieht:


Spoiler: Code





```
public void laden() {
        try {
            XMLDecoder d = new XMLDecoder(
                                new FileInputStream("Wellensittiche.xml"));
            wellensittiche = (ArrayList<Wellensittich>) d.readObject();
            d.close();
          
            for(int i=0; i<wellensittiche.size(); i++) {
                Vector rowData = new Vector();
                rowData.add(wellensittiche.get(i).getName());
                rowData.add(wellensittiche.get(i).getGeschlecht());
                rowData.add(wellensittiche.get(i).getGeburtsdatum());
                rowData.add(wellensittiche.get(i).getZuchtform());
                rowData.add(wellensittiche.get(i).getFarbschlag());
                rowData.add(wellensittiche.get(i).getErkrankungen());
                rowData.add(wellensittiche.get(i).getLieblingsfutter());
                model.addRow(rowData);
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(TabelleV2.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
  
    public void speichern() {
        ArrayList<Wellensittich> wellensittiche = new ArrayList();
      
        model.getDataVector();
        Vector<Vector<String> > v = model.getDataVector();
      
        for(int i=0; i<v.size(); i++)
            wellensittiche.add(new Wellensittich(v.get(i).get(0), v.get(i).get(1), v.get(i).get(2), v.get(i).get(3), v.get(i).get(4), v.get(i).get(5), v.get(i).get(6)));
        try {
            XMLEncoder e = new XMLEncoder(
                            new FileOutputStream("Wellensittiche.xml")
            );
          
            e.writeObject(wellensittiche);
            e.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(TabelleV2.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
```
Erläuterung:
Ich speichere die Informationen einfach in einer ArrayList, diese speichere ich dann in die Datei. Deshalb habe ich beim auslesen dann ein Objekt des Typs ArrayList<Wellensitiich>. Da da jetzt alles drin steht gehe ich anschließend nur noch die Liste durch und erzeuge eine Zeile(rowData.add...), welche ich anschließend der Tabelle hinzufüge. Vorher gucke ich noch, ob schon was in der Tabelle steht. Wenn ja lösche ich alles raus. Somit stehen am Ende nur die Einträge aus der Datei in der Tabelle.
Beim speichern lese ich sämtliche Daten aus der Tabelle Zeile für Zeile aus und erzeuge mit diesen Daten einen Wellensittich(die ewig lange Zeile). Das Erzeugte Objekt wird in die Liste geschrieben und am Ende wird die Liste in die Datei geschrieben.



Viel Glück mit dem TabbedPane 
P.S.: Ich habe das einfach in deinen Code reingeschrieben und dabei ist mir was aufgefallen:
Du hast die Tabelle quasi doppelt auf dem Pane

```
panelTabelle.add(tabelle);
panelTabelle.add(new JScrollPane(tabelle));
```
Da reicht die zweite Zeile.

Und bitte mach das als vernünftige Klassen mit Methoden!


----------



## birdy (30. Dez 2016)

ich glaube deine Lösung ist tatsächlich eleganter als meine  ArrayList entspricht auch mehr so dem, was wir bis jetzt gelernt haben, aber ich bin froh, dass ich das mit Brechen und Biegen auch endlich hinbekommen habe  wenn ich da später noch Lust zu habe und du nichts dagegen hast, kann ich meinen Ansatz ja nochmal überarbeiten 

ich werde so viele Klassen und Methoden raushauen wie nur geht!!  nein also immerhin hab ich jetzt schonmal für jede Tabelle eine Klasse  es ist ein Anfang


----------



## Libentis (30. Dez 2016)

Hab bestimmt nichts dagegen 
Glaube ich dir  Ich muss auch noch was für die Uni machen und seh total dagegen an, weil ich bisher noch nicht mal einen Ansatz habe... 

Na dann^^ Hauptsache das steht nicht alles in der Main


----------



## birdy (30. Dez 2016)

ok, cool, danke 

also ich würde dir ja meine Hilfe anbieten ... aber ich glaube die wirst du nicht nötig haben 

nein nein, ich werd mich drum kümmern 
riesen Danke für deine Hilfe bisher


----------



## Libentis (30. Dez 2016)

Kd 

Kommt drauf an, du kennst dich wahrscheinlich nicht mit Algorithmen aus?


----------



## birdy (30. Dez 2016)

das ist leider erst Teil im nächsten Semester


----------

