Kapselung JProgressBar in JTable, aber getValueAt() greift nicht

Hildi0

Mitglied
Hallo, ich möchte euch zuerst mal das Problem zeigen:

Java:
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class JTable1 {
    static class Bar extends JProgressBar implements TableCellRenderer {
        private final String description;

        public Bar(String description) {
            this.description = description;
            setStringPainted(true);
        }

        public String getDescription() {
            return description;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            return this;
        }
    }

    static class Model extends AbstractTableModel {
        List<Bar> bars = new ArrayList<>();

        public void addABar() {
            bars.add(new Bar(String.valueOf((char) (new Random().nextInt(10) + 'a'))));
        }

        public void setTestValue() {
            bars.forEach(bar -> bar.setValue(25));
        }

        @Override
        public int getRowCount() {
            return bars.size();
        }

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            if (columnIndex == 0) {
                return bars.get(rowIndex).getDescription();
            }
            if (columnIndex == 1) {
                return bars.get(rowIndex); // does not work
            }
            return null;
        }

        @Override
        public String getColumnName(int column) {
            String[] names = {"Description", "Progress"};
            return names[column];
        }
    }

    public static void main(String[] args) {
        Model model = new Model();
        JTable table = new JTable(model);
        table.getColumnModel().getColumn(1).setCellRenderer(new Bar("something"));
        model.addABar();
        model.addABar();
        JFrame frame = new JFrame();
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);

        model.setTestValue();
        model.fireTableDataChanged();
    }
}

Der Fortschritt der Bar ist immer 0, denn getValueAt() funktioniert aus einem mir unerklärlichen Grund nicht...

So würde es funktionieren, aber ich frage mich wieso:

Java:
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class JTable2 {
    static class Bar extends JProgressBar implements TableCellRenderer {
        private final String description;

        public Bar(String description) {
            this.description = description;
            setStringPainted(true);
        }

        public String getDescription() {
            return description;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            return this;
        }
    }

    static class Model extends AbstractTableModel {
        List<Bar> bars = new ArrayList<>();

        public void addABar() {
            bars.add(new Bar(String.valueOf((char) (new Random().nextInt(10) + 'a'))));
        }

        public void setTestValue() {
            bars.forEach(bar -> bar.setValue(25));
        }

        @Override
        public int getRowCount() {
            return bars.size();
        }

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            if (columnIndex == 0) {
                return bars.get(rowIndex).getDescription();
            }
            if (columnIndex == 1) {
                return bars.get(rowIndex); // does not work
            }
            return null;
        }

        @Override
        public String getColumnName(int column) {
            String[] names = {"Description", "Progress"};
            return names[column];
        }
    }

    public static void main(String[] args) {
        Model model = new Model();
        JTable table = new JTable(model) {
            @Override
            public TableCellRenderer getCellRenderer(int row, int column) {
                if (column == 1) {
                    return (TableCellRenderer) model.getValueAt(row, column);
                }
                return super.getCellRenderer(row, column);
            }
        };
        model.addABar();
        model.addABar();
        JFrame frame = new JFrame();
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);

        model.setTestValue();
        model.fireTableDataChanged();
    }
}

Weiß da vielleicht jemand bescheid? Vielen Dank. 😊
 

mihe7

Top Contributor
Ganz einfach: Du setzt ja den Renderer
table.getColumnModel().getColumn(1).setCellRenderer(new Bar("something"));
Und diese Instanz wird von JTable verwendet und die liefert einfach eine Referenz auf sich selbst (this) zurück:
Java:
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            return this;
        }

Da Du den Wert dieser Instanz nicht änderst, wird also immer 0 angezeigt.

Entweder hast Du etwas ganz abstruses vor oder Dir fehlt der Sinnzusammenhang zwischen Model der Renderer. Normalerweise liefert das Model Daten und der Renderer stellt diese dar. Dafür wird das Flyweight-Pattern verwendet, d. h. die Komponente (hier Deine Bar) wird wie ein Stempel verwendet, so dass man mit einer einzigen (EDIT: Instanz der) Komponente alle Zellen zeichnen kann.

Was genau willst Du denn machen?
 

Hildi0

Mitglied
Vielen Dank für Deine Antwort. 🤓 So richtig habe ich noch nicht verstanden, weshalb ich zwingend die Methode getCellRenderer von JTable überschreiben muss...

Was genau willst Du denn machen?
Ich möchte in einer Spalte einer JTable eine JProgressBar anzeigen, die den Fortschritt einer aktuellen Operation (in der Zeile) anzeigt. Dafür soll der Wert der JProgressBar zum Beispiel einmal pro Sekunde aktualisiert werden. Also zum Beispiel soll der Fortschritt von Downloads angezeigt werden.
 

mihe7

Top Contributor
So richtig habe ich noch nicht verstanden, weshalb ich zwingend die Methode getCellRenderer von JTable überschreiben muss...
Musst Du ja nicht :) Ganz grob: Die JTable holt sich vom Model einen Wert (getValueAt), nimmt den registrierten Renderer und ruft getTableCellRendererComponent auf, dabei wird unter anderem der Wert übergeben.

Der Renderer liefert nun eine Komponente zurück. Diese Komponente wird nicht zur JTable hinzugefügt sondern von JTable nur zum Zeichnen verwendet (wie ein Stempel).

Ich möchte in einer Spalte einer JTable eine JProgressBar anzeigen, die den Fortschritt einer aktuellen Operation (in der Zeile) anzeigt. Dafür soll der Wert der JProgressBar zum Beispiel einmal pro Sekunde aktualisiert werden. Also zum Beispiel soll der Fortschritt von Downloads angezeigt werden.
Gut, Du hast also ein TableModel, mit einer Spalte, die Werte z. B. von 0 bis 100 annimmt und diese Werte möchtest Du jetzt in Form eines Fortschrittbalkens anzeigen lassen.

Mom, ich bastel mal schnell was zusammen.
 

mihe7

Top Contributor
So, Du meinst vermutlich etwas in der Richtung:
Java:
import javax.swing.*;
import javax.swing.table.*;
import java.util.Random;

public class Test {
    static class ProgressRenderer implements TableCellRenderer {
        private JProgressBar bar;

        public ProgressRenderer() {
            bar = new JProgressBar();
        }

        @Override
        public JComponent getTableCellRendererComponent(JTable table, Object value, 
                boolean isSelected, boolean hasFocus, int row, int column) {
            int progress = 0;
            if (value != null && value instanceof Number) {
                progress = ((Number) value).intValue();
            }
            bar.setValue(progress);
            return bar;
        }
    }

    public void run() {
        final Random rand = new Random();
        DefaultTableModel model = new DefaultTableModel(new Object[][]{
                {"Task #1", rand.nextInt(100)},
                {"Task #2", rand.nextInt(100)}
            }, 
            new Object[]{"Description", "Progress"}
        );

        JTable table = new JTable(model);
        table.getColumnModel().getColumn(1).setCellRenderer(new ProgressRenderer());
        
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setVisible(true);

        new Timer(1000, e -> model.setValueAt(rand.nextInt(100), rand.nextInt(2), 1)).start();
    }

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

Hildi0

Mitglied
Ja, aber jetzt wird ja dieselbe JProgressBar (d.h.: dasselbe Objekt) immer wiederverwendet? Oder ist das das Flyweight-Pattern-Prinzip?
 

mihe7

Top Contributor
Ja, aber jetzt wird ja dieselbe JProgressBar (d.h.: dasselbe Objekt) immer wiederverwendet? Oder ist das das Flyweight-Pattern-Prinzip?
Ja und ja. So funktioniert die JTable.

Nachtrag: wie oben geschrieben wird ein Objekt wie ein Stempel verwendet. Zelle 1: Stempel einstellen, Stempel andrücken, Zelle 2: Stempel einstellen, Stempel andrücken usw.

Durch den Renderer (Flyweight-Pattern) kann die JTable große Datenmengen ohne nennenswerten Speicherverbrauch darstellen. Außerdem ist es so relativ einfach möglich, die Daten nicht im Speicher halten zu müssen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D jProgressBar soll bei 100% sein wenn sql Abfrage inkl. jTable schreiben fertig ist... Java Basics - Anfänger-Themen 5
S Thread.sleep mit JProgressBar Java Basics - Anfänger-Themen 1
E jProgressbar, 6 Versuche, welche value angeben ? Java Basics - Anfänger-Themen 3
E jProgressBar auf 0 stellen Java Basics - Anfänger-Themen 1
E JProgressbar Java Basics - Anfänger-Themen 8
M JProgressBar wird nicht richtig angezeigt Java Basics - Anfänger-Themen 8
S JProgressbar mit individuellem Start/Endpunkt Java Basics - Anfänger-Themen 11
V Zugriff auf jProgressbar Java Basics - Anfänger-Themen 10
S JProgressBar richtig anwenden Java Basics - Anfänger-Themen 27
N JProgressBar Java Basics - Anfänger-Themen 8
K Threads jProgressBar update Java Basics - Anfänger-Themen 14
J JProgressBar - wird nicht geupdated Java Basics - Anfänger-Themen 3
H JProgressBar wird nicht aktualisiert Java Basics - Anfänger-Themen 7
S jProgressBar läuft nicht! Java Basics - Anfänger-Themen 13
H Aktualisierung des JProgressBar in Abhängigkeit eines Threads Java Basics - Anfänger-Themen 5
Y jprogressbar beenden? Java Basics - Anfänger-Themen 4
L JProgressBar für FileUpload Java Basics - Anfänger-Themen 3
B Pseudo JProgressBar Java Basics - Anfänger-Themen 3
G JProgressBar - XP style Java Basics - Anfänger-Themen 4
G JProgressBar während dem ausführen einer Funktion Java Basics - Anfänger-Themen 3
S jProgressBar Java Basics - Anfänger-Themen 3
G JProgressBar Java Basics - Anfänger-Themen 2
G JProgressBar#2 Java Basics - Anfänger-Themen 2
G JProgressBar Java Basics - Anfänger-Themen 7
G jProgressBar value aus anderer Klasse heraus verändern Java Basics - Anfänger-Themen 7
B jProgressBar mit while nicht for Java Basics - Anfänger-Themen 13
K JProgressbar, zur laufzeit steuern Java Basics - Anfänger-Themen 7
V JProgressBar anklickbar? Java Basics - Anfänger-Themen 2
A Timer + JProgressBar Java Basics - Anfänger-Themen 4
G in JProgressBar Fortschritt anzeigen Java Basics - Anfänger-Themen 8
P JDialog & JProgressBar Java Basics - Anfänger-Themen 2
Z Problem mit JProgressBar Java Basics - Anfänger-Themen 4
richis-fragen JTable den angezeigten WERT nicht den Wert aus dem Model ausgeben. Java Basics - Anfänger-Themen 3
richis-fragen JTable Header ausgeblendete (width = 0) nicht per mouseDragged aufziehen. Java Basics - Anfänger-Themen 9
richis-fragen JTable sowohl Spaltennamen wie auch Spaltenbeschriftungen Java Basics - Anfänger-Themen 7
richis-fragen JTable effektiv angezeigter Text ausgeben nicht Inhalt vom Model Java Basics - Anfänger-Themen 9
G JTable Listselectionlistener friert das Programm ein Java Basics - Anfänger-Themen 8
Mady Daten von JList & Combobox in JTable adden Java Basics - Anfänger-Themen 2
W Liste mit Listen in JTable darstellen Java Basics - Anfänger-Themen 1
J Zelleninhalt einer Jtable löschen Java Basics - Anfänger-Themen 2
E JTable einzelne Zelle färben Java Basics - Anfänger-Themen 2
thobren jtable arraylist Java Basics - Anfänger-Themen 12
thobren JTable Icon Java Basics - Anfänger-Themen 1
R Compiler-Fehler JTable mit XML befüllen | The constructor JTable(Object[], String[]) is undefined Java Basics - Anfänger-Themen 10
G JTable, Zeile auswählen und Ergebnis an Schaltfläche übergeben Java Basics - Anfänger-Themen 4
J Jtable Eingabe nach Klick ausserhalb der Tabelle übernehmen Java Basics - Anfänger-Themen 6
J JTable Spalteninhalt löschen Java Basics - Anfänger-Themen 1
J JTable Titel wird nicht angezeigt Java Basics - Anfänger-Themen 6
B jTable Spalte summieren Java Basics - Anfänger-Themen 7
N JTable auslesen Java Basics - Anfänger-Themen 6
O JTable in Excel mit Farben Java Basics - Anfänger-Themen 8
O Kommentar auf JTable Zelle Java Basics - Anfänger-Themen 2
M Jtable Reenderer Java Basics - Anfänger-Themen 0
O Popoup Menü im JTable richtig anzeigen Java Basics - Anfänger-Themen 6
M Jtable änderung updaten Java Basics - Anfänger-Themen 2
O JTable Suchfunktion Java Basics - Anfänger-Themen 2
M jTable bekommt null Java Basics - Anfänger-Themen 1
M JTable an andere Klasse übergeben Java Basics - Anfänger-Themen 2
M Datenbank in jTable Laden Java Basics - Anfänger-Themen 49
M Klasse in JTable einfügen Java Basics - Anfänger-Themen 7
S JTable Java Basics - Anfänger-Themen 16
S JTable mit Daten füllen Java Basics - Anfänger-Themen 7
L JTable Tagebuch Spaltenhöhe verändern Java Basics - Anfänger-Themen 3
S JTable - Filter an anderen Colums Java Basics - Anfänger-Themen 2
R JTable Suchfunktion mit SQL Daten Java Basics - Anfänger-Themen 2
C JTable update mit MySQL Datenbank Java Basics - Anfänger-Themen 1
C Best Practice JTable in MVC Pattern Java Basics - Anfänger-Themen 7
J Daten einer Textdatei in ein JTable importieren. Java Basics - Anfänger-Themen 3
A zykl. Aktualisierne JTable Java Basics - Anfänger-Themen 9
C Endlosschleife bei füllen von Daten im JTable Java Basics - Anfänger-Themen 5
C Werte aus JTable auslesen Java Basics - Anfänger-Themen 4
A Probleme beim zykl. aktulisieren von Daten in JTable Java Basics - Anfänger-Themen 3
V JTable welcher Listener ? Java Basics - Anfänger-Themen 7
D Falsche Zeile wird in JTable gelöscht Java Basics - Anfänger-Themen 6
D MySQL Abfrage in JTable speichern Java Basics - Anfänger-Themen 43
D JTable Zeile wird nicht in MySQL gelöscht Java Basics - Anfänger-Themen 16
D JTable Zeilen löschen Java Basics - Anfänger-Themen 5
C Klassen JTable wird ohne Header aufgebaut Java Basics - Anfänger-Themen 6
K (JTable) Text einer Zelle auf der linken Seite kürzel Java Basics - Anfänger-Themen 2
B Kniffel JTable Java Basics - Anfänger-Themen 5
N JTable flackert Java Basics - Anfänger-Themen 8
T JTable Daten aus txt datei Java Basics - Anfänger-Themen 3
J ArrayList wird in JTable falsch angezeigt Java Basics - Anfänger-Themen 0
J Eintragen von Personen in JTable Java Basics - Anfänger-Themen 4
X JTable mit grünen und roten Punkten Java Basics - Anfänger-Themen 2
LexeB4F DEL --> JTable Zelleninhalt Java Basics - Anfänger-Themen 3
R JTable Auslesen Java Basics - Anfänger-Themen 1
Crazynet jTable erste Zeile mit deffinierten Werten Java Basics - Anfänger-Themen 0
K Collections Sortieren nach zweiter Spalte in JTable Java Basics - Anfänger-Themen 18
J JTable Wert gleich überschreiben Java Basics - Anfänger-Themen 6
S Zeile entfernen aus JTable Java Basics - Anfänger-Themen 15
S JTable clonen Java Basics - Anfänger-Themen 5
H Best Practice PDF JTable Java Basics - Anfänger-Themen 4
S In JTable Zeile selektieren mit Mausklick Java Basics - Anfänger-Themen 16
D JTable Probleme beim Sortieren von Zahlen. Java Basics - Anfänger-Themen 6
M JTable mit XML datei befüllen Java Basics - Anfänger-Themen 1
F Zeile bei JTable hinzufügen Java Basics - Anfänger-Themen 6
K JTable Bild einfügen Java Basics - Anfänger-Themen 1
M [JTable] getValue throws ArrayOutOfBoundException Java Basics - Anfänger-Themen 1
B JTable - Highlighter ??? Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben