Swing AbstractTableModel

Zeppi

Aktives Mitglied
Moin, ich versuche gerade ein JTable zu füllen mit einer ArrayList. Bei meinem Programm ist es so, dass man immer gefragt wird, was eingegeben werden soll, das wird in der ArrayList gespeichert. In der ArrayList steht dann immer ein Name und eine Zeit. Aber wenn ich dann damit versuche das 2d Array für den Table zufüllen, werden bei mir natürlich immer die Daten überschrieben und es steht dann in der Tabelle immer das Gleiche. Das liegt daran, das im JDialog immer eine neue Tabelle aufgerufen wird, dadurch fängt das 2d Array immer von vorne an und speichert dann den neusten Wert an jeder Position. Vielleicht kann jemand mal ein Blick drüber werfen und mir Tipps geben.

[CODE lang="java" title="JDialog"]public class HighDialog extends JDialog {

public HighDialog(String name, int zeit) {
JTable table = new JTable(new Tabelle(name, zeit)); //hier wird immer der neue JTable aufgerufen
table.setSize(400, 400);
add(new JScrollPane(table));
table.setVisible(true);
setSize(500, 500);
}
}[/CODE]
[CODE lang="java" title="AbstractTableModel"]public class Tabelle extends AbstractTableModel {
private Highscore highscore = Highscore.getInstance(); //ist ein Singleton und die ArrayList
final String[] spaltenBeschriftung = { "Spielername", "Zeit" };
final Object[][] data = new Object[10][2]; //größe der Tabelle

public Tabelle(String name, int zeit) { //bekommt die Werte vom JDialog übergeben
highscore.add(new Score(name, zeit)); //hier wird die ArrayList gefüllt mit einem Score. Score besteht aus einem String spielername und int Sekunden
for (int i = 0; i < highscore.size(); i++) { //dadurch, dass das immer von 0 beginnt, werden die ersten Werte des Arrays data überschrieben
for (Score s : highscore) { //hier wird jeder Score von Highscore durchlaufen

data[0] = s.getSielername(); //spielername wird gespeichert
data[1] = s.getSekunden(); //zeit des spieler werden gespeichert
}
}
}
}[/CODE]
[CODE lang="java" title="JPanel"]//wenn mein Spiel gewonnen wurde, wird das durchgeführt
String name = JOptionPane.showInputDialog(this, "Name");
if (name != null) {
Highdialog dia = new HighDialog(name,zeit); //hier wird name und zeit dem Dialog übergeben,
//weil ich nicht wusste, wie sonst die Tabelle die Werte bekommt,
//damit die ArrayList gefüllt wird.
dia.setVisible(true);[/CODE]

Vielleicht hat jemand ein Tipp bzw. Verbesserungen.
Danke Zeppi
 

mihe7

Top Contributor
Gib dem Konstruktor von HighDialog doch einfach eine Instanz von Tabelle mit, dann brauchst Du diese im Konstruktor nicht neu zu erzeugen.
 

Zeppi

Aktives Mitglied
Gib dem Konstruktor von HighDialog doch einfach eine Instanz von Tabelle mit, dann brauchst Du diese im Konstruktor nicht neu zu erzeugen.
Meinst du so?
Java:
public class HighDialog extends JDialog {
    private Highscore highscore = Highscore.getInstance();
    private Tabelle tabelle = new Tabelle();

    public HighDialog(String name, int zeit) {
        highscore.add(new Score(name, zeit));
        JTable table = new JTable(tabelle);
        table.setSize(400, 400);
        add(new JScrollPane(table));
        table.setVisible(true);
        setSize(500, 500);
 
Zuletzt bearbeitet:

Zeppi

Aktives Mitglied
Nein, ich meine so:
Java:
public class HighDialog extends JDialog {

    public HighDialog(Tabelle tabelle) {
        JTable table = new JTable(tabelle);
        table.setSize(400, 400);
        add(new JScrollPane(table));
        table.setVisible(true);
        setSize(500, 500);
    }
}
Achso, aber da verändert sich nicht wirklich etwas. Wenn ich jetzt zwei unterschiedliche Namen hintereinander eingebe, haben beide Einträge die selben Daten.
 

mihe7

Top Contributor
Doch, da verändert sich sehr viel: Du erzeugst nun keine neue Tabellen-Instanz mehr. Das Problem, das Du ansprichst, ist auf etwas anderes zurückzuführen. Vermutlich willst Du in Deinem TableModel noch eine add-Methode einführen, um eine übergebene Highscore in der Liste einzutragen.
 

Zeppi

Aktives Mitglied
Doch, da verändert sich sehr viel: Du erzeugst nun keine neue Tabellen-Instanz mehr. Das Problem, das Du ansprichst, ist auf etwas anderes zurückzuführen. Vermutlich willst Du in Deinem TableModel noch eine add-Methode einführen, um eine übergebene Highscore in der Liste einzutragen.
Genau! Ich habe es ja mit dem Konstruktor versucht. Aber dadurch fängt die Liste immer von vorne an und überschreibt die Daten.
 

mihe7

Top Contributor
Es gibt verschiedene Möglichkeiten, das hängt davon ab, wie die Aktualisierung im UI stattfinden soll. Ich gehe mal davon aus, dass Du eine Tabelle anzeigst und in einem Dialog willst Du der Tabelle nun eine Zeile hinzufügen.

Wenn Highscore außer einer popligen List nichts bietet, dann muss die JTable und Dein Dialog das selbe TableModel verwenden, das seinerseits eine add-Implementierung anbietet. Der Dialog ruft dann einfach dieses add auf und die JTable zeigt die Änderung automatisch an. BTW: die Highscore braucht kein Singleton zu sein.
 

mihe7

Top Contributor
Hier mal im Zusammenhang:
Java:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.*;

public class Test {
    // Kurze Implementierung, damit wir was zu zeigen haben
    static class Score {
        public final String name;
        public final int points;

        public Score(String name, int points) {
            this.name = name;
            this.points = points;
        }
    }

    static class ScoreTable extends AbstractTableModel {
        private static final String[] COLUMNS = {
            "Name", "Punkte"
        };

        private List<Score> scores;

        public ScoreTable(List<Score> scores) {
            this.scores = scores;
        }

        // hier die add-Methode
        public void add(Score score) {
            int newIndex = 0;
            int numRows = getRowCount();
            while (newIndex < numRows && 
                    score.points < scores.get(newIndex).points) {
                newIndex++;
            }
            
            scores.add(newIndex, score);
            fireTableRowsInserted(newIndex, newIndex);
        }

        @Override public int getRowCount() { return scores.size(); }
        @Override public int getColumnCount() { return COLUMNS.length; }
        @Override public String getColumnName(int col) { return COLUMNS[col]; }
        @Override public Object getValueAt(int row, int col) {
            Score score = scores.get(row);
            switch(col) {
                case 0: return score.name;
                case 1: return Integer.toString(score.points);
            }
            return "";
        }
    }

    // wir haben nur eine Instanz der Highscores
    private List<Score> highscore = new ArrayList<>();
    private ScoreTable scores = new ScoreTable(highscore);

    public void newHighScore() {
        final JTextField nameField = new JTextField(50);
        final JTextField pointsField = new JTextField();
        JPanel panel = new JPanel(new GridLayout(0,1));
        panel.add(new JLabel("Name:"));
        panel.add(nameField);
        panel.add(new JLabel("Punkte:"));
        panel.add(pointsField);

        boolean valid;  
        do {
            valid = true;
            int result = JOptionPane.showConfirmDialog(null, panel, 
                "Neue Highscore", JOptionPane.OK_CANCEL_OPTION);
            if (result == JOptionPane.OK_OPTION) {
                try {
                    String name = nameField.getText();
                    int points = Integer.parseInt(pointsField.getText());
                    scores.add(new Score(name, points)); // zur Highscore-Tabelle hinzufügen
                } catch (NumberFormatException ex) {
                    valid = false;
                }
            }
        } while (!valid);
        
    }

    public void run() {
        JTable table = new JTable(scores); // highscores in Tabelle anzeigen
        JButton button = new JButton("Neue Highscore");
        button.addActionListener(e -> newHighScore());

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.add(button, BorderLayout.SOUTH);
        frame.setSize(800, 600);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Test().run());
    }
}
 

Zeppi

Aktives Mitglied
Hier mal im Zusammenhang:
Java:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.*;

public class Test {
    // Kurze Implementierung, damit wir was zu zeigen haben
    static class Score {
        public final String name;
        public final int points;

        public Score(String name, int points) {
            this.name = name;
            this.points = points;
        }
    }

    static class ScoreTable extends AbstractTableModel {
        private static final String[] COLUMNS = {
            "Name", "Punkte"
        };

        private List<Score> scores;

        public ScoreTable(List<Score> scores) {
            this.scores = scores;
        }

        // hier die add-Methode
        public void add(Score score) {
            int newIndex = 0;
            int numRows = getRowCount();
            while (newIndex < numRows &&
                    score.points < scores.get(newIndex).points) {
                newIndex++;
            }
           
            scores.add(newIndex, score);
            fireTableRowsInserted(newIndex, newIndex);
        }

        @Override public int getRowCount() { return scores.size(); }
        @Override public int getColumnCount() { return COLUMNS.length; }
        @Override public String getColumnName(int col) { return COLUMNS[col]; }
        @Override public Object getValueAt(int row, int col) {
            Score score = scores.get(row);
            switch(col) {
                case 0: return score.name;
                case 1: return Integer.toString(score.points);
            }
            return "";
        }
    }

    // wir haben nur eine Instanz der Highscores
    private List<Score> highscore = new ArrayList<>();
    private ScoreTable scores = new ScoreTable(highscore);

    public void newHighScore() {
        final JTextField nameField = new JTextField(50);
        final JTextField pointsField = new JTextField();
        JPanel panel = new JPanel(new GridLayout(0,1));
        panel.add(new JLabel("Name:"));
        panel.add(nameField);
        panel.add(new JLabel("Punkte:"));
        panel.add(pointsField);

        boolean valid; 
        do {
            valid = true;
            int result = JOptionPane.showConfirmDialog(null, panel,
                "Neue Highscore", JOptionPane.OK_CANCEL_OPTION);
            if (result == JOptionPane.OK_OPTION) {
                try {
                    String name = nameField.getText();
                    int points = Integer.parseInt(pointsField.getText());
                    scores.add(new Score(name, points)); // zur Highscore-Tabelle hinzufügen
                } catch (NumberFormatException ex) {
                    valid = false;
                }
            }
        } while (!valid);
       
    }

    public void run() {
        JTable table = new JTable(scores); // highscores in Tabelle anzeigen
        JButton button = new JButton("Neue Highscore");
        button.addActionListener(e -> newHighScore());

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.add(button, BorderLayout.SOUTH);
        frame.setSize(800, 600);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Test().run());
    }
}
Klasse. Danke für die ausführliche Beschreibung. Ich werde das gleich mal umbauen und bei mir versuchen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
N Swing Print JTable mit AbstractTableModel AWT, Swing, JavaFX & SWT 1
N JTable, AbstractTableModel aus Datenbank initialisieren AWT, Swing, JavaFX & SWT 8
I JTable,AbstractTableModel Problem AWT, Swing, JavaFX & SWT 3
I JTable und AbstractTableModel AWT, Swing, JavaFX & SWT 10
H JTable - DefaultTableModel vs AbstractTableModel AWT, Swing, JavaFX & SWT 5
O Swing AbstractTableModel - Observer.. AWT, Swing, JavaFX & SWT 14
K Swing jTable und AbstractTableModel AWT, Swing, JavaFX & SWT 6
Ollek Swing JTable - Zeile löschen mit AbstractTableModel AWT, Swing, JavaFX & SWT 20
B Swing AbstractTableModel rows verschieben AWT, Swing, JavaFX & SWT 2
M Swing JComboBox im AbstractTableModel AWT, Swing, JavaFX & SWT 8
H Markierte Zeile löschen AbstractTableModel AWT, Swing, JavaFX & SWT 10
K JTable & AbstractTableModel AWT, Swing, JavaFX & SWT 9
G Problem mit AbstractTableModel und JComboBox AWT, Swing, JavaFX & SWT 8
P Eigenes TableModel abgeleitet von AbstractTableModel (neue rows nicht sichtbar) AWT, Swing, JavaFX & SWT 6
Lony AbstractTableModel Exception in thread "AWT-EventQueue- AWT, Swing, JavaFX & SWT 3
G AbstractTableModel kopieren AWT, Swing, JavaFX & SWT 4
G JTable (AbstractTableModel) wird nicht aktualisiert AWT, Swing, JavaFX & SWT 2
F AbstractTableModel + Vector - Wie Zeile hinzufügen AWT, Swing, JavaFX & SWT 4
D JTable, DefaultTableCellRenderer & AbstractTableModel AWT, Swing, JavaFX & SWT 11
N JTable repaint mit AbstractTableModel AWT, Swing, JavaFX & SWT 2
B jTabel, MVC und AbstractTableModel AWT, Swing, JavaFX & SWT 6
M Wann AbstractTableModel und wann DefaultTableModel AWT, Swing, JavaFX & SWT 4
S AbstractTableModel AWT, Swing, JavaFX & SWT 16

Ähnliche Java Themen


Oben