JTable erstellen, um einen Bestand zu pflegen

birdy

Mitglied
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 :p
- Bea
 

Libentis

Aktives Mitglied
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

Mitglied
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

Aktives Mitglied
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

Mitglied
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

Aktives Mitglied
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 :D

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

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

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

Libentis

Aktives Mitglied
Dann vielleicht :D

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.

Java:
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

Mitglied
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 :D
 

birdy

Mitglied
jaa, also das mit der Tabelle klappt schonmal ein Stück weit besser :D
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 ...
 

Libentis

Aktives Mitglied
Top :D
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.

Java:
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?
 

Anhänge

  • Tabelle.jpg
    Tabelle.jpg
    49,4 KB · Aufrufe: 38
  • Tabelle.jar
    13,7 KB · Aufrufe: 3

birdy

Mitglied
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 :D darf ich fragen, wie lange du dafür gebraucht hast? :D
 

birdy

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

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

Aktives Mitglied
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 :D

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

Mitglied
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 :D

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 :D

Java:
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 :D

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 :D
 

Libentis

Aktives Mitglied
Ich programmiere aber ziemlich sicher mehr als du :D 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 :D
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... :D
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

Mitglied
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 :D

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:

Java:
 //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 :D 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 :D 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 :p

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

Libentis

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

Kd. Aaah. Das ist gut.
Erneut: Kd :D 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 :mad:

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

birdy

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

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 :D

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

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

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

Aktives Mitglied
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 :D
 

birdy

Mitglied
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 :D

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

aber es klappt nicht :(
 

Libentis

Aktives Mitglied
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 :D
 

birdy

Mitglied
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:

Code:
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 :confused:
 

Libentis

Aktives Mitglied
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

Mitglied
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 :eek:
 

Libentis

Aktives Mitglied
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? :D
Außerdem habe Ich da gerade sowieso ausversehen was verwechselt. Dir müsste eine ArrayList reichen, ich war bei vector aus c++, sry :D
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

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

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

Aktives Mitglied
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 :D
 

Libentis

Aktives Mitglied
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 :D
 

birdy

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

Libentis

Aktives Mitglied
Top :)
Ich habs gerade auch gemacht :D :D
Falls es dich interessiert wie es bei mir aussieht:
Java:
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
Java:
panelTabelle.add(tabelle);
panelTabelle.add(new JScrollPane(tabelle));
Da reicht die zweite Zeile.

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

birdy

Mitglied
ich glaube deine Lösung ist tatsächlich eleganter als meine :D 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 :D 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!! :D nein also immerhin hab ich jetzt schonmal für jede Tabelle eine Klasse :cool: es ist ein Anfang :D
 

Libentis

Aktives Mitglied
Hab bestimmt nichts dagegen :D
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... :D

Na dann^^ Hauptsache das steht nicht alles in der Main :eek::D
 

birdy

Mitglied
ok, cool, danke :)

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

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

Oben