JTable mehrere Spalten sortieren

JavaRentner

Aktives Mitglied
Guten Tag.
Habe das Problem, wenn ich mehrere Spalten (abhängig von der zuvor sortierten Spalte) sortiere, dass immer nur auf der letzten Spalte das Pfeil-Arrow angezeigt wird.

Den Arrow-Pfeil painte ich mit folgender Klasse, die ich in diesem Forum bekommen und etwas angepasst habe.
Java:
public class RTableHeaderRenderer extends DefaultTableCellRenderer implements Formate {
    private static final long serialVersionUID = 1L;
    public static final int NONE = 0;    //NONE    KEINE Sortierung
    public static final int UP = 1;        //DESC    kleinste UNTEN    (Absteigend)
    public static final int DOWN = 2;    //ASC    kleinste OBEN    (Aufsteigend)

    private int sortDirection = NONE;
    private String sortedColumnTitle = null;
    private static int arrowSize = 8;
   
 
    public RTableHeaderRenderer() {
        setHorizontalAlignment(SwingConstants.CENTER);
    }

    public void setSortDirection(int sortDirection, String columnTitle) {
        this.sortDirection = sortDirection;
        this.sortedColumnTitle = columnTitle;
       
       
        if(sortDirection != NONE) {
            System.out.println("columnTitle = "+columnTitle);
        }
       
//        repaint();
//        update(getGraphics());
    }
   
    protected void paintComponent(Graphics g) {
        setOpaque(false);
        setBorder(header);
        setVerticalAlignment(0);
        setFont(RTable.getHeadFont());
        Color headerColor = RTable.getHeaderColor();
//        setBackground(headerColor);
        Color fC = ColorHandler.fontColor(headerColor);
        setForeground(fC);
        super.paintComponent(g);
       
        if (sortedColumnTitle == null || sortedColumnTitle.isEmpty()) {
            return; // No sorting specified
        }

        int x = getWidth() - arrowSize - 3;
        int y = (getHeight() - arrowSize) / 2;

        if (Objects.equals(getText(), sortedColumnTitle)) {
            if (sortDirection == UP) {
                Polygon arrow = new Polygon();
                arrow.addPoint(x, y + arrowSize);
                arrow.addPoint(x + arrowSize, y + arrowSize);
                arrow.addPoint(x + arrowSize / 2, y);
                g.setColor(fC);
                ((Graphics2D) g).fill(arrow);
            }
            else if (sortDirection == DOWN) {
                Polygon arrow = new Polygon();
                arrow.addPoint(x, y);
                arrow.addPoint(x + arrowSize, y);
                arrow.addPoint(x + arrowSize / 2, y + arrowSize);
                g.setColor(fC);
                ((Graphics2D) g).fill(arrow);
            }
        }
    }
}

Da die Daten aus MySQL DB mit der vom Anwender definierten Sortierung (z.B. ORDER BY datum DESC, name ASC) kommen, wollte ich die Arrow-Pfeile bei den Spalten mit obigem Code entsprechend setzen.

Gibt es dazu eine Lösung? Ist es überhaubt möglich im JTableHeader mehrere Spalten zu sortieren!
Vielen Dank.

PS:
Mehrer Spalten sortieren habe ich mit dem Comporator hingekriegt! Nur das mit dem Arrow nicht.
 
Zuletzt bearbeitet:

Robert Zenz

Top Contributor
Spontan sieht die Logik ganz gut aus, aber du setzt hier nur einen Spaltennamen als sortiert. Kann es sein dass Logik darueber immer nur den letzten setzt, anstatt hier eine Liste an Spaltennamen zu uebergeben?
 

JavaRentner

Aktives Mitglied
Vielen Dank!
Genau das hab ich zwischenzeitlich auch herausgefunden!
Mein Code sieht jetzt so aus:
Java:
public class RTableHeaderRenderer extends DefaultTableCellRenderer implements Formate {
    private static final long serialVersionUID = 1L;
    public static final int NONE = 0;    //NONE    KEINE Sortierung
    public static final int UP = 1;        //DESC    kleinste UNTEN    (Absteigend)
    public static final int DOWN = 2;    //ASC    kleinste OBEN    (Aufsteigend)

    private int sortDirection[] = null;
    private String sortedColumnTitle[] = null;
    private static int arrowSize = 8;
   
 
    public RTableHeaderRenderer() {
        setHorizontalAlignment(SwingConstants.CENTER);
    }

    public void setSortDirection(int[] sortDirection, String[] columnTitle) {
        this.sortDirection = sortDirection;
        this.sortedColumnTitle = columnTitle;
       
       
        if(sortDirection != null && !columnTitle[0].equals("NONE")) {
            System.out.println("columnTitle = "+java.util.Arrays.toString(columnTitle));
        }
       
//        repaint();
//        update(getGraphics());
    }
   
    protected void paintComponent(Graphics g) {
        setOpaque(false);
        setBorder(header);
        setVerticalAlignment(0);
        setFont(RTable.getHeadFont());
        Color headerColor = RTable.getHeaderColor();
//        setBackground(headerColor);
        Color fC = ColorHandler.fontColor(headerColor);
        setForeground(fC);
        super.paintComponent(g);
       
        if (sortedColumnTitle == null || sortedColumnTitle.length <= 0) {
            return; // No sorting specified
        }

        int x = getWidth() - arrowSize - 3;
        int y = (getHeight() - arrowSize) / 2;

        for(int i=0; i<sortDirection.length; i++) {
            int sortInt = sortDirection[i];
            String sortColumnTitel = sortedColumnTitle[i];
           
            if (Objects.equals(getText(), sortColumnTitel)) {
                if (sortInt == UP) {
                    Polygon arrow = new Polygon();
                    arrow.addPoint(x, y + arrowSize);
                    arrow.addPoint(x + arrowSize, y + arrowSize);
                    arrow.addPoint(x + arrowSize / 2, y);
                    g.setColor(fC);
                    ((Graphics2D) g).fill(arrow);
                }
                else if (sortInt == DOWN) {
                    Polygon arrow = new Polygon();
                    arrow.addPoint(x, y);
                    arrow.addPoint(x + arrowSize, y);
                    arrow.addPoint(x + arrowSize / 2, y + arrowSize);
                    g.setColor(fC);
                    ((Graphics2D) g).fill(arrow);
                }
            }
           
           
        }
    }
}
Man beachte die Zeilen 7 und 8.
in der Methode :
protected void paintComponent(Graphics g)
habe ich jetzt eine Schleife eingebaut!
Passt perfekt!!! 😄

Im Moment ist das Problem gelösst.
 

JavaRentner

Aktives Mitglied
Mehrer Spalten sortieren habe ich mit dem Comporator hingekriegt!
Stimmt leider nicht!

Ich sortiere die Spalte datum und will jetzt, dass es die namen innerhalb der Datums sortiert.
Wie stelle ich das an.
Mit folgendem Code kann ich jeweils nur die angeklickte Spalte sortieren:
Code:
    class MyComparator implements Comparator<Object[]> {
        protected boolean isSortAsc;
        protected int isSortCol1;

        public MyComparator(boolean sortAsc, int sortCol) {
            isSortAsc = sortAsc;
            isSortCol1 = sortCol;
        }
        public int compare(Object[] o1, Object[] o2) {
            int result = 0;
            Object test1 = o1[isSortCol1];
            Object test2 = o2[isSortCol1];
            if (test1 instanceof String) {
                result = ((String)test1).compareTo((String)test2);
            }
            else if (test1 instanceof Integer) {
                try {
                    result = ((Integer)test1).compareTo((Integer)test2);
                } catch (Exception e) {}
            }
            else if (test1 instanceof Double) {
                try {
                    result = ((Double)test1).compareTo((Double)test2);
                } catch (Exception e) {}
            }
            else if (test1 instanceof Date) {
                try {
                    result = ((Date)test1).compareTo((Date)test2);
                } catch (Exception e) {}
            }
            else if (test1 instanceof Boolean) {
                try {
                    result = ((Boolean)test1).compareTo((Boolean)test2);
                } catch (Exception e) {}
            }
            if (!isSortAsc) {
                result = -result;
            }
            return result;
        }
    }
Wo, wie muss ich den Code ändern, was muss ich noch übergeben, dass er mir zuerst spalte1 dann spalte2 (innerhalb spalte1) und dann
noch spalte3 (innerhalb spalte1, spalte2) sortiert?
Habe was gefunden:
implements Comparable<SortModel>
aber da blicke ich nicht durch. :mad:
 

Robert Zenz

Top Contributor
Dein Comparator muss dynamisch anhand der Spaltenliste funktionieren. Also in Pseudo-Code:

Java:
for (int sortIndex = 0; sortIndex < sortColumnNames.length; sortIndex++) {
    String columnName = sortColumnNames[sortIndex];
    SortOrder sortOrder = sortOrders[sortIndex];
  
    Object value1 = getFirstComparisonValueForColumn(columnName);
    Object value2 = getSecondComparisonValueForColumn(columnName);
   
    int comparedValue = Objects.compare(value1, value2);
   
    if (comparedValue != 0) {
        return comparedValue;
    }
}

return 0;

Wenn die Werte ident sind, wird einfach weitergemacht bis man unterschiedliche findet, oder sie sind halt gleich.
 

Crian

Top Contributor
Falls das Problem noch nicht gelöst ist, kann ich aus meinem Code mal ein kleines, lauffähiges Beispiel mit dem TableRowSorter basteln. Denn ich meine, der macht genau das: Wenn man erst nach Spalte A, dann nach Spalte B, und am Ende nach Spalte C sortiert, ist es nach dem Muster C > B > A sortiert, wenn ich das nicht falsch beobachtet habe.
 

Crian

Top Contributor
Ich hab einfach mal eines zusammengebastelt zum Herumspielen:

row_sortter.jpg

Klasse RowSorterMain:

Java:
package stc.java.forum.swing.rowsorter;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import stc.java.forum.swing.rowsorter.data.RowSorterData;
import stc.java.forum.swing.rowsorter.table.RowSorterTable;

public class RowSorterMain {

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

    private static void createAndShowGUI() {
        JFrame frame = new JFrame();
        frame.setTitle("Row-Sorter-Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        List<RowSorterData> dataSets = createDataSets();
        RowSorterTable table = new RowSorterTable(dataSets);

        frame.add(table.getPanel(), BorderLayout.CENTER);
        frame.setPreferredSize(new Dimension(800, 600));
        frame.pack();
        frame.setVisible(true);
    }

    private static List<RowSorterData> createDataSets() {
        List<RowSorterData> dataSets = new ArrayList<>();
        dataSets.add(new RowSorterData( 1,  -5.22, "Apfel",     "Porsche",  "Buche"  ));
        dataSets.add(new RowSorterData( 1,  -5.22, "Birne",     "Peugeot",  "Birke"  ));
        dataSets.add(new RowSorterData( 1,  -5.22, "Traube",    "Honda",    "Eiche"  ));
        dataSets.add(new RowSorterData( 1,  17.8,  "Banane",    "Mercedes", "Esche"  ));
        dataSets.add(new RowSorterData( 1,  17.8,  "Orange",    "BMW",      "Tanne"  ));
        dataSets.add(new RowSorterData( 1,  17.8,  "Zitrone",   "VW",       "Lärche" ));
        dataSets.add(new RowSorterData( 1,  22.22, "Papelmuse", "Audi",     "Platane"));
        dataSets.add(new RowSorterData( 1,  22.22, "Pfirsich",  "Toyota",   "Zeder"  ));

        dataSets.add(new RowSorterData( 2, 22.22,  "Apfel",     "Porsche",  "Buche"  ));
        dataSets.add(new RowSorterData( 2, 22.22,  "Birne",     "Peugeot",  "Birke"  ));
        dataSets.add(new RowSorterData( 2, -5.22,  "Traube",    "Honda",    "Eiche"  ));
        dataSets.add(new RowSorterData( 2, -5.22,  "Banane",    "Mercedes", "Esche"  ));
        dataSets.add(new RowSorterData( 2, 22.22,  "Orange",    "BMW",      "Tanne"  ));
        dataSets.add(new RowSorterData( 2, 17.8,   "Zitrone",   "VW",       "Lärche" ));
        dataSets.add(new RowSorterData( 2, 17.8,   "Papelmuse", "Audi",     "Platane"));
        dataSets.add(new RowSorterData( 2, 17.8,   "Pfirsich",  "Toyota",   "Zeder"  ));

        dataSets.add(new RowSorterData( 3,   0.2,  "Apfel",     "Porsche",  "Buche"  ));
        dataSets.add(new RowSorterData( 3,   3.75, "Birne",     "Peugeot",  "Birke"  ));
        dataSets.add(new RowSorterData( 3,  -5.22, "Traube",    "Honda",    "Eiche"  ));
        dataSets.add(new RowSorterData( 3,  17.8,  "Banane",    "Mercedes", "Esche"  ));
        dataSets.add(new RowSorterData( 3,   0.1,  "Orange",    "BMW",      "Tanne"  ));
        dataSets.add(new RowSorterData( 3,   1.2,  "Zitrone",   "VW",       "Lärche" ));
        dataSets.add(new RowSorterData( 3,  22.22, "Papelmuse", "Audi",     "Platane"));
        dataSets.add(new RowSorterData( 3, -13.2,  "Pfirsich",  "Toyota",   "Zeder"  ));
        return dataSets;
    }

}

Klasse RowSorterData:

Code:
package stc.java.forum.swing.rowsorter.data;

public class RowSorterData {

    private final int ganzeZahl;

    private final double gleitpunktzahl;

    private final String obst;

    private final String auto;

    private final String baum;

    public RowSorterData(int ganzeZahl, double gleitpunktzahl, String obst, String auto,
            String baum) {
        this.ganzeZahl = ganzeZahl;
        this.gleitpunktzahl = gleitpunktzahl;
        this.obst = obst;
        this.auto = auto;
        this.baum = baum;
    }

    public int getGanzeZahl() {
        return ganzeZahl;
    }

    public double getGleitpunktzahl() {
        return gleitpunktzahl;
    }

    public String getObst() {
        return obst;
    }

    public String getAuto() {
        return auto;
    }

    public String getBaum() {
        return baum;
    }

}

Klasse RowSorterTable:

Code:
package stc.java.forum.swing.rowsorter.table;

import java.awt.BorderLayout;
import java.awt.Component;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableRowSorter;

import stc.java.forum.swing.rowsorter.data.RowSorterData;

public class RowSorterTable {

    private final JPanel panel;

    private final JTable table;

    private final JScrollPane scrollPane;

    public RowSorterTable(List<RowSorterData> dataSets) {
        table = new JTable();
        table.getTableHeader().setReorderingAllowed(false);

        RowSorterTableModel tableModel = new RowSorterTableModel(dataSets);
        table.setModel(tableModel);

        RowSorterColumnModel columnModel = new RowSorterColumnModel();
        table.setColumnModel(columnModel);

        TableRowSorter<RowSorterTableModel> sorter = new TableRowSorter<>(tableModel);
        table.setRowSorter(sorter);

        scrollPane = new JScrollPane(table);
        scrollPane.getVerticalScrollBar().setUnitIncrement(30);

        panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(scrollPane, BorderLayout.CENTER);
    }

    public Component getPanel() {
        return panel;
    }

}

Klasse RowSorterTableModel:

Code:
package stc.java.forum.swing.rowsorter.table;

import java.util.List;

import javax.swing.table.AbstractTableModel;

import stc.java.forum.swing.rowsorter.data.RowSorterData;

public class RowSorterTableModel extends AbstractTableModel {

    private static final long serialVersionUID = 1L;
    private static final int NUMBER_OF_COLUMNS = 5;


    private final List<RowSorterData> dataSets;

    public RowSorterTableModel(List<RowSorterData> dataSets) {
        super();
        this.dataSets = dataSets;
    }

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

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

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        RowSorterData data = dataSets.get(rowIndex);
        switch (columnIndex) {
            case 0:
                return data.getGanzeZahl();
            case 1:
                return data.getGleitpunktzahl();
            case 2:
                return data.getObst();
            case 3:
                return data.getAuto();
            case 4:
                return data.getBaum();
            default:
                throw new RuntimeException("Unzuläsiger Spaltenindex '" + columnIndex + "'.");
        }
    }

    @Override
    public Class<?> getColumnClass(int column) {
        switch (column) {
            case 0:
                return Integer.class;
            case 1:
                return Double.class;
            case 2:
            case 3:
            case 4:
                return String.class;
            default:
                return String.class;
        }
    }

}

Klasse RowSorterColumnModel:

Code:
package stc.java.forum.swing.rowsorter.table;

import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;

public class RowSorterColumnModel extends DefaultTableColumnModel  {

    private static final long serialVersionUID = 1L;

    public RowSorterColumnModel() {
        int colNumber = 0;

        TableColumn column0 = new TableColumn(colNumber++, 100);
        column0.setHeaderValue("Ganze Zahl");
        column0.setMinWidth(50);
        addColumn(column0);

        TableColumn column1 = new TableColumn(colNumber++, 100);
        column1.setHeaderValue("Gleitkommazahl");
        column1.setMinWidth(50);
        addColumn(column1);

        TableColumn column2 = new TableColumn(colNumber++, 100);
        column2.setHeaderValue("Obst");
        column2.setMinWidth(50);
        addColumn(column2);

        TableColumn column3 = new TableColumn(colNumber++, 100);
        column3.setHeaderValue("Auto");
        column3.setMinWidth(50);
        addColumn(column3);

        TableColumn column4 = new TableColumn(colNumber++, 100);
        column4.setHeaderValue("Baum");
        column4.setMinWidth(50);
        addColumn(column4);
    }

}

Das ganze sieht dann so aus, wenn man est nach "Obst", dann nach "Gleitkommazahl" und dann nach "Ganze Zahl" sortiert:

row_sorter_2.jpg
 

JavaRentner

Aktives Mitglied
Vielen dank @Crian
funktioniert SUPER und auch schnell wenn keine 30 Datensätze vorhanden sind.

Habe jetzt Deine Klasse mittels Schleife befeuert...
private static List<RowSorterData> createDataSets()
mit einer Artikelliste von 105'512 Datensätzen...
(das war die Tabelle mit den wengisten Records)

Das füllen dauerte mehr als 2Min.
Sortieren ging dann ganz fix.

Jetzt gibt es aber Tabellen die haben mehr als 1 Mio. Records. (ungefiltert)
Das wären dann ca. 20 Min. zum laden.

Wenn ich aber den Rowsorter und das RowSorter-ColumnModel nicht verwende, wird auch die grösste Tabelle innerhalb von 10 Sek. geladen!
Nur das Sortieren funkioniert halt nicht wie gewünscht.

Ich glaub ich habe mal wieder gar nichts verstanden... :oops:

Werde noch ein bischen üben... 😄
 

Crian

Top Contributor
Bei so großen Mengen versagt das ganze natürlich irgendwann. Ich habe mir dann auch Gui-Elemente geschrieben (leider keine Tabellen, die ich dir weitergeben könnte), welche Treffer wie Suchfunde auf Internet-Suchseiten etc. darstellen. Da werden dann die Daten auch erst geladen,wenn sich der Benutzer die betreffende Seite anschaut.

Das nun mit so einer Tabelle zu verheiraten ist schwierig. Selbst wenn du nicht alles anzeigst, würdest du ja die ersten x Datensätze anzeigen wollen, wenn der Benutzer die Spalte sortiert, und dazu müsstest du im Hintergrund ja dann doch alle Datensätze sortieren. Hmmm.

Ich fürchte bei nach oben offener Menge kommt jedes System, dass die Ergebnisse nicht irgendwie portioniert (z.B. Seitenweise) an seine Grenzen.

Bei mir nutze ich das u.a., um Vokabeln, die bestimmten Suchkriterien genügen, anzuzeigen. Innerhalb dieser sortiere ich aber nicht, sondern filtere nach den Vorgaben, die der Benutzer macht.

Das sieht in dem Fall so aus:

erweiterter_Suchdialog.jpg

Ohne die Sucheingabe "Baum" wären es 606 Seiten, so sind es nur drei. Falls dir etwas in de Art etwas nutzt, kann ich versuchen, daraus auch ein kleines, ausführbares Beispiel zu basteln. Das biete nur leider nicht das Sortieren in deinem Sinne. Vermutlich solltest du dir nochmal genau überlegen, was der Benutzer an der Stelle alles machen können soll, und wie man das erreichen könnte.

Wie man sieht hab ich da auch schon ein paar weitere Dinge eingebaut, z.B. wie viele Spalten ich auf der Seite darstelle und wie viele gefundene Objekte. Da ist der Phantasie natürlich keine Grenze gesetzt, nur die Anzeige von so vielen Treffern gleichzeitig wird wohl erst in vielen Jahren problemlos gehen, wenn die Rechner wirklich weiterhin immer schneller werden sollten. :)
 

Crian

Top Contributor
Eventuell konnte man die Anzeige ja so schreiben, dass eine Tabelle angezeigt wird, wenn es weniger als X Treffer sind.
Je nach Benutzern ist zwei Minuten Ladezeit für 100k Elemente auch zu viel, die meisten sind dann schon fort, zumindest im Internet.
 

Oneixee5

Top Contributor
Selbst wenn du nicht alles anzeigst, würdest du ja die ersten x Datensätze anzeigen wollen, wenn der Benutzer die Spalte sortiert, und dazu müsstest du im Hintergrund ja dann doch alle Datensätze sortieren.
Man kann "virtual tables" verwenden. Je nach Umsetzung schaffen diese große Datenmengen auch in Echtzeit. Die Daten werden unabhängig vom UI sortiert oder gefiltert und nur der relevante Ausschnitt wir im UI gerendert. Daten, bis zu einer gewissen Größe kann man im Arbeitsspeicher halten, wenn dieser nicht mehr ausreicht kann man auf eine DB ausweichen.

Allerdings kann man eine "nach oben offener Menge" weder sortieren noch filtern, das Ergebnis wäre wahrscheinlich immer falsch. Das ist aber ein theoretisches Szenario, welches so nicht vorkommen wird. Für Dinge wie Ereignislisten oder Fehlerprotokolle, welche sich während der Ansicht immer weiter verändern/anwachsen, kann man geeignete Strategien entwickeln: bspw: dynamische Hinweistexte oder Färbung bei Änderung.
 

Lennox-n

Mitglied
Ja, das Sortieren der Daten ist natürlich nicht das Problem... sondern das Rendering selbiger... wobei man dasselbe Problem auch hätte, wenn gar nicht sortiert würde. Aber, bevor das langsam wird, braucht man schon sehr viele Reihen
 

Robert Zenz

Top Contributor
Das nun mit so einer Tabelle zu verheiraten ist schwierig. Selbst wenn du nicht alles anzeigst, würdest du ja die ersten x Datensätze anzeigen wollen, wenn der Benutzer die Spalte sortiert, und dazu müsstest du im Hintergrund ja dann doch alle Datensätze sortieren. Hmmm.
Du kannst natuerlich Paging mit Lazy-Loading kombinieren. Die JVxTable macht das zum Beispiel. Es werden X Saezte gefetcht, und wenn der Benutzer weit genug nach unten scrollt werden die naechsten geladen. Ich muss aber ehrlich zugeben dass ich den Mechanismus noch nie betrachtet habe, nur dass er da ist.

Also du fetcht quasi die ersten 100 Zeilen (die meisten JDBC-Treiber kennen einen "Cursor" Modus wo man die Zeilen einzeln holen kann und nicht alles ueber die Leitung schicken muss), dann lauscht du auf der Scrollbar darauf ob sie das letzte, sagen wir mal, Drittel erreicht hat, und wenn ja, fetch du wieder 100 Zeilen. So in der Art.
 

JavaRentner

Aktives Mitglied
Wer lädt denn solche Mengen in ein UI - und wozu? Es braucht zwar 20 Min. zum Laden aber 3 Jahre zum Durchlesen.
Womit Du absolut RECHT hast... 😁

Aber nur in der Tabelle (lokal) sind die Daten entschlüsselt und können somit gefiltert werden!

Folgende, in der DB geschriebenen Einträge sind die exakt gleichen Nachnamen:
g1E1g5b6g9
K7w298H284

könnten aber auch zwei gleiche Geburtsdaten sein:
g1E1g5b6g9
K7w298H284


Entschlüsselt können sie erst im lokal gestarteten Programm werden.
Eine Filterabfrage, wenn 1000 Kunden den gleichen Nachnamen haben, kann so nicht generiert werden.

Nur schon die Abfrage " WHERE nachname = 'Muster'" würde vorraussetzen, dass ich weiss wieviele den Nachnamen Muster
und welche Verschlüsselungs-Algorithmen diese haben, und müssten dann 1000 mal verschlüsselt werden

Darum muss das Sortieren und / oder das Filtern auf der aktuellen Tabelle der lokalen Anwendung geschehen.

Hoffe ich habe mich erklärt... 😯
 

Lennox-n

Mitglied
Na ja, JVx ist aber ein zusätzliches Framework (für Java EE?), das von einem privaten Unternehmen entwickelt und gepflegt wird. Solche Abhängigkeiten möchte man normalerweise nicht haben, wenn auch 10 zusätzliche Codezeilen zum gleichen Ergebnis führen. Zudem setzt JVx auf eine andere Schichtenarchitektur (womöglich auch auf ein anderes Paradigma), an die man sich erst einmal gewöhnen sollte. Aber wenn Entwicklungszeit hier keine kritische Anforderung ist, kann man es probieren
 

KonradN

Super-Moderator
Mitarbeiter
Aber nur in der Tabelle (lokal) sind die Daten entschlüsselt und können somit gefiltert werden!
Das ist ein Szenario, das man wirklich prüfen muss. Wieso ist es wichtig, dass die Daten verschlüsselt abgelegt werden in der Datenbank? Du raubst Dir damit viele Features, die die Datenbank dir sonst eigentlich liefert. Einige Datenbanken bieten oft eine Encryption der Daten in der Datenbank, aber der Client kann einen Schlüssel bereit stellen so dass letzten Endes die Datenbank selbst die Entschlüsselung machen kann (Das gibt einem dann wieder die Operationen, aber zu sehr schlechten Konditionen, da immer noch ein Table Scan notwendig wird für Filter!)

Aber selbst in dem Szenario: Das Problem ist ja das Rendering - und nicht das Sortieren der Daten. (Wenn es die Sortierung selbst wäre, dann könnte man das natürlich auch optimieren über halt die Vorhaltung von Reihenfolgen...) Du kannst also prinzipiell alles laden (so der Hauptspeicher ausreicht) und dann alle Daten sortieren. Aber Du fügst in die Tabelle immer nur die Zeilen, die Du auch wirklich anzeigen must (oder die halt am Rand sind).

Das Szenario, das Robert Zenz beschreibt, ist dabei relativ einfach umzusetzen, aber rennt auch in die gleichen Probleme, wenn ein Anwender immer weiter herunter scrollt. Irgendwann sind dann halt auch alle Werte in der Tabelle hinzugefügt.

Daher wäre aus meiner Sicht das günstigste, wenn man ein Paging implementieren würde. Da kann man dem user auch anbieten, die Page Größe selbst zu bestimmen. Wartezeiten hat er dann halt selbst zu verantworten....
 

JavaRentner

Aktives Mitglied
Das ist ein Szenario, das man wirklich prüfen muss. Wieso ist es wichtig, dass die Daten verschlüsselt abgelegt werden in der Datenbank?
Es ist eine Datenbank auf die von etlichen Ausendienstmitarbeiter zugegriffen wird.
(Also auf einem Host im Internet oder einem Server der von aussen erreichbar sein muss.)

Wenn also erwähnte Datenbank gehackt wird, kann niemand damit was anfangen.
Oder können Sie mir grad mal sagen was folgende zwei Strings im Klartext heissen?:
g1E1g5b6g9
K7w298H284

Zu erwähnen ist, dass auch die Spaltenüberschrift verschlüsselt ist!

Der Algorithmus ist nicht mal mir bekannt, da er bei der Installation generiert, unter berücksichtigung der DB, wird und gleich verschlüsselt wird.
(in der DB sind keine natürlichen Informationen dazu vorhanden)

Verwendbar wird er nur dann, wenn etwas entschlüsselt werden muss.
Ansonsten ist die Klasse auf eine ganz eigene art verschlüsselt und wird nur kurz entschlüsselt eingebunden wenn sie benötigt wird,
und gleich nach verwendung wird die Klasse wieder eliminiert. Wenn versucht wird die Klasse in der laufenden Anwendung abzufangen,
zerreist es die Informationen in der Anwendung.

Danke für Deinen Input...
Du raubst Dir damit viele Features, die die Datenbank dir sonst eigentlich liefert.
Auf diese Features kann und will gerne verzichten.

Das Szenario, das Robert Zenz beschreibt, ist dabei relativ einfach umzusetzen, aber rennt auch in die gleichen Probleme, wenn ein Anwender immer weiter herunter scrollt. Irgendwann sind dann halt auch alle Werte in der Tabelle hinzugefügt.
Habe ich eben auch gerade herausgefunden.

Daher wäre aus meiner Sicht das günstigste, wenn man ein Paging implementieren würde. Da kann man dem user auch anbieten, die Page Größe selbst zu bestimmen. Wartezeiten hat er dann halt selbst zu verantworten....
Genau daran will ich jetzt arbeiten.
Es soll mit der aktuellen Tabelle der Anwendung arbeiten... soviel habe ich schon rausgefunden.

Vielen Dank @KonradN

PS: Nachtrag
Das einzige was ich ohne Verschlüsselung anwenden kann ist die ID und AKTIV.
"Where AKTIV AND ID = n" resp. nur "WHERE AKTIV"
 

KonradN

Super-Moderator
Mitarbeiter
Es ist eine Datenbank auf die von etlichen Ausendienstmitarbeiter zugegriffen wird.
(Also auf einem Host im Internet oder einem Server der von aussen erreichbar sein muss.)
Da einfach einmal ein paar Hinweise von meiner Seite zu diesem Thema:

a) Bei Datenbanken ist es eigentlich nicht empfohlen, diese direkt erreichbar zu machen. Datenbanken gelten eher als unsicher - alleine schon der Punkt DoS (Denial of Service) ist hier zu nennen. Üblich sind daher Gateways, die dann die Daten z.B. per REST Webservices bereit stellen. Da gibt es dann entsprechende Vorkehrungen zur Absicherung, die man dann problemlos umsetzen kann.

b) Generell wäre dann auch die Überlegung, dass man das dann alles komplett ins Web verlagert.

c) Der Thread hier zeigt doch gerade:
Auf diese Features kann und will gerne verzichten.
das dies eben nicht wirklich der Fall ist. Vor allem wenn es um Aussendienstmitarbeiter geht - da ist auch ein Herunterladen aller Daten schon extrem problematisch. So ein Mitarbeiter wird ja ggf. auch mal mit einer schlechteren Verbindung klar kommen müssen ....
Da wäre es also durchaus wichtig, dass man eben die Daten selbst nicht unbedingt laden muss, um an die Daten, die man eben benötigt, heran zu kommen.

d) Sicherheit der Verschlüsselung
Wenn also erwähnte Datenbank gehackt wird, kann niemand damit was anfangen.
Oder können Sie mir grad mal sagen was folgende zwei Strings im Klartext heissen?:
g1E1g5b6g9
K7w298H284
Dazu kann ich noch nicht wirklich viel sagen. Die Frage ist hier, wie Du verschlüsselst. Verschlüsselung ist eine extrem kritische Sache und da ist es enorm schwer, eine gute Verschlüsselung hin zu bekommen. So typische Wege für so Verschlüsselungen könnte z.B. sein:

  • Die Daten selbst werden durch einen symetrischen Schlüssel verschlüsselt. Dieser liegt nur auf einem REST Gateway (verschlüsselt) vor.
  • User haben einen Asynchronen Schlüssel. Wenn sie denn Zugriff haben, dann wird damit Ihre verschlüsselte Kopie des symetrischen Schlüssels entsperrt. Das sorgt dann dafür, dass Du gezielt User entfernen kannst ohne dass da alle User/Clients betroffen sind.

Die Clients haben dann mit der Verschlüsselung in der Datenbank nichts zu tun. Sie haben lediglich:
  • die SSL Verschlüsselung mit dem Server aufzubauen (https)
  • Die asynchrone Verschlüsselung zu öffnen - also in der Regel den private Key freizuschalten oder zu geben.

Das ist aber nur eine grobe Skizzierung. Etwas in der Art bietet der Microsoft SQL Server (evtl. nur Enterprise Edition) an. MySQL Enterprise evtl. auch, aber da bin ich nicht sicher, wie die das alles aufgebaut haben, da ich mir das im Detail nie angesehen habe.

Ein Kernproblem aus meiner Sicht bei Deinem Vorgehen: Wenn die Clients die Verschlüsselung machen, dann sind diese immer alle betroffen und alle angreifbar. Wenn ich also Zugriff bekomme, dann kann ich das ggf. schnell auslesen (ggf. in dem ich mir deine Java Software ansehe. Im Worst case darf ich halt ein Tool wie Ghidra nutzen, ob da halt die Abläufe im Detail zu beobachten und um die Ver- und Entschlüsselung so auszulesen... Die Sicherheit ist also unter dem Strich nicht wirklich hoch. (Und das, ohne den Algorithmus zu betrachten. Selbst da gibt es ja extrem viele Angriffsvektoren ... schon die falsche Wahl eines Zufallsgenerators kann da komprimitierend sein ....

Aber wir kennen ja keinerlei Details, daher ist das kein Urteil oder so.... Aber Verschlüsselung sollte man generell nie selbst machen und statt dessen auf vertrauenswürdige Algorithmen und Libraries zurück greifen ... und selbst da muss man sich einarbeiten ...
 

JavaRentner

Aktives Mitglied
Aber wir kennen ja keinerlei Details, daher ist das kein Urteil oder so....
Ich eigentlich auch nicht.

Aber Verschlüsselung sollte man generell nie selbst machen
Habe ich auch nicht... Den Algorithmus hat ein Dr. der Mathematik gemacht.

... statt dessen auf vertrauenswürdige Algorithmen und Libraries zurück greifen
Welche dann Weltweit bekannt sind?

Ich glaube wir können hier die Diskusion abbrechen, zumal ich davon überhaubt nichts verstehe. :rolleyes:
 

Lennox-n

Mitglied
Das, was Konrad schreibt, ist richtig. Die Datenbank sollte nicht direkt erreichbar sein (immer nur intern/lokal), und alle Daten sollten mit einem sicheren und erprobten Hashverfahren verschlüsselt sein. Es gibt da zum Beispiel Argon2, bcrypt, scrypt oder PBKDF2, siehe zum Beispiel hier oder hier. Alle haben natürlich Vor- und Nachteile, gelten aber momentan als sicher - und haben gemein, dass sie Einwegehashfunktionen sind. Das heißt falls eine Person an diese Daten gelangen sollte, kann sie ohne den Schlüssel (und Salt...) (bzw. ohne die Ursprungsdaten) damit nichts anfangen, lediglich, ob Daten vorhanden sind (Existenz), ist bekannt
 

Robert Zenz

Top Contributor
Na ja, JVx ist aber ein zusätzliches Framework (für Java EE?), das von einem privaten Unternehmen entwickelt und gepflegt wird. Solche Abhängigkeiten möchte man normalerweise nicht haben, wenn auch 10 zusätzliche Codezeilen zum gleichen Ergebnis führen. Zudem setzt JVx auf eine andere Schichtenarchitektur (womöglich auch auf ein anderes Paradigma), an die man sich erst einmal gewöhnen sollte.
Deswegen sagte ich "macht zum Beispiel", wie in "Anschauungsbeispiel". Eine Umstellung von reinem Java auf JVx-Swing ist etwas komplexer weil man auch die Datenbankschicht fuer die Komponenten verwenden muss, und nur dann anratsam wenn man es will.
 

KonradN

Super-Moderator
Mitarbeiter
Ohne es in die Länge ziehen zu wollen:

a) Gewisse Probleme sind da und Du wurdest aufmerksam gemacht. So Dir bewusst ist, dass die Missachtung gewisser Dinge grob fahrlässig sein könnte und die Konsequenzen entsprechend aussehen könnten, ist alles ok.

b) Es spielt keine Rolle, von wem der Algorithmus kommt. Es ist wichtig, dass er nach aktuellem Wissenstand als sicher gilt. Nimm nur die SSL Verschlüsselung: Da gibt es diverse Algorithmen und viele gelten nicht mehr als sicher. (Nimm einfach einmal einen alten IE6 und verbinde dich mit einem aktuellen Webserver. Dann wirst Du feststellen, dass keine Verbindung möglich ist, da es keine Überschneidung bei den Algorithmen mehr gibt.)
 

Oneixee5

Top Contributor
Wenn also erwähnte Datenbank gehackt wird, kann niemand damit was anfangen.
Oder können Sie mir grad mal sagen was folgende zwei Strings im Klartext heissen?:
g1E1g5b6g9
K7w298H284
Dazu mal eine Anfrage an eine KI meiner Wahl - das Muster und die Länge sind mir auch sofort aufgefallen - daher die Recherche:
Ein Softwareanbieter betont, dass diese selbstentwickelte Verschlüsselung sehr sicher wäre. kannst du das bestätigen, 2 Beispieltexte: g1E1g5b6g9 K7w298H284

Hier muss ich dir leider dringend abraten. Basierend auf deiner Beschreibung und den Beispieltexten läuten bei mir alle Alarmglocken.
Ich kann nicht bestätigen, dass dies sicher ist. Im Gegenteil: Es gibt starke Indizien dafür, dass es sich um unsichere "Schlangenöl"-Kryptografie handelt.
Hier ist die Analyse, warum du skeptisch sein solltest:

1. Das "Selbstentwickelt"-Problem​


In der Kryptografie gilt die goldene Regel: "Don't roll your own crypto" (Entwickle keine eigene Verschlüsselung).
  • Standard: Sichere Verschlüsselung (wie AES, RSA, ChaCha20) ist öffentlich, mathematisch bewiesen und wurde von tausenden Experten jahrelang auf Schwachstellen geprüft.
  • Proprietär: Wenn ein Anbieter sagt, er habe etwas "Eigenes" entwickelt, bedeutet das meistens "Security by Obscurity" (Sicherheit durch Geheimhaltung). Sobald ein Angreifer herausfindet, wie der Algorithmus funktioniert (was durch Reverse Engineering der Software leicht möglich ist), ist der Schutz meist sofort weg.

2. Analyse der Beispieltexte​


Schauen wir uns die Strings an:
g1E1g5b6g9
K7w298H284
Hier sind die Auffälligkeiten, die gegen eine moderne Verschlüsselung sprechen:
  • Mustererkennung (Red Flag):
    Im ersten Beispiel (g1E1g5b6g9) taucht der Buchstabe 'g' dreimal und die Zahl '1' zweimal auf.
    • Warum ist das schlecht? Moderne Verschlüsselung (wie AES) erzeugt Ausgaben, die von absolutem Zufallsrauschen nicht zu unterscheiden sind.
    • Wenn der Klartext Muster hat (z.B. "Banane"), darf der Chiffretext keine Muster haben. Dass hier Zeichen so oft wiederholt werden, deutet auf eine simple Substitution (Ersetzung) oder eine schwache Kodierung hin. Das ist oft trivial zu knacken.
  • Die Länge:
    Die Texte sind extrem kurz (10 Zeichen).
    • Eine sichere Verschlüsselung benötigt meist einen sogenannten "Initialisierungsvektor" (IV) oder "Nonce", um sicherzustellen, dass das gleiche Wort verschlüsselt jedes Mal anders aussieht. Ein IV allein ist oft schon länger als diese 10 Zeichen.
    • Es sieht eher aus wie ein generiertes Passwort oder ein Hash-Wert, aber nicht wie ein sicher verschlüsselter Datenblock.
  • Zeichensatz:
    Es sieht aus wie einfaches Alphanumerisch (a-z, A-Z, 0-9). Echte verschlüsselte Daten sind binär (Bytes). Um sie darzustellen, nutzt man meist Base64 (was oft mit = endet oder + und / enthält) oder Hexadezimal (nur 0-9 und A-F). Das hier sieht nach etwas "Gebasteltem" aus.

3. Das Urteil​


Es ist höchstwahrscheinlich keine Verschlüsselung, sondern eher eine Obfuskation (Verschleierung) oder eine sehr schwache, amateurhafte Kodierung.
Ein professioneller Anbieter würde sagen: "Wir nutzen AES-256 im GCM-Modus."
Ein unseriöser Anbieter sagt: "Wir haben eine eigene, unknackbare Methode entwickelt."

Empfohlenes Vorgehen​


Du solltest den Anbieter mit konkreten Fragen konfrontieren. Akzeptiere keine Marketing-Aussagen.
Stelle dem Anbieter diese Fragen:
  1. Welcher mathematische Standard-Algorithmus wird verwendet (z.B. AES, Twofish)?
  2. Welche Schlüssellänge wird verwendet (z.B. 256 Bit)?
  3. Wie wird das Schlüsselmanagement betrieben (wo liegen die Keys)?
  4. Wurde der Algorithmus von unabhängigen Dritten auditiert (Pentest)?
 

KonradN

Super-Moderator
Mitarbeiter
Also der TE hat ja keine Details gegeben.

Ich hatte bei seinen Beispielen ein ungutes Gefühl, aber wenn er eine Verschlüsselung will, die das Format (Alphabet, Länge) beibehält, dann gibt es prinzipiell auch sowas. FF1 (Format-Preserving Encryption, FPE, NIST SP 800-38G) basiert auf AES und ist damit prinzipiell relativ sicher. Durch die kleine Domäne wird es aber problematisch. Wenn man also nur 4 Ziffern (0-9) verschlüsselt und den Wert ggf. kennt, dann kann man da die 10000 möglichen Werte einfach durchspielen... ==> Also von der Sicherheit her nicht unproblematisch.

Aber prinzipiell würde das also auch gehen (Aber halt nicht bei wirklich sicherheitsrelevanten Dingen).

Ich hatte mal einen Anwendungsfall für FF1. Da habe ich FF1 als AES basierte Verschlüsselung für Push Nachrichten auf Handies verwendet, die potenziell auch personenbezogene Daten enthalten konnten.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
K mehrere DB Einträge in einem JTable darstellen ?HILFE! Java Basics - Anfänger-Themen 2
G JTable bei aktivieren einer Zelle soll Text selektiert werden. Java Basics - Anfänger-Themen 24
G JTable setModel(myModel) ok -> wie wieder unset machen? Java Basics - Anfänger-Themen 8
G JTable den angezeigten WERT nicht den Wert aus dem Model ausgeben. Java Basics - Anfänger-Themen 3
G JTable Header ausgeblendete (width = 0) nicht per mouseDragged aufziehen. Java Basics - Anfänger-Themen 9
G JTable sowohl Spaltennamen wie auch Spaltenbeschriftungen Java Basics - Anfänger-Themen 7
G 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 3
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
H Kapselung JProgressBar in JTable, aber getValueAt() greift nicht Java Basics - Anfänger-Themen 7
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
S JTable LinkedList <Objekt> befüllen Java Basics - Anfänger-Themen 1
S JTable dynamisch mit Datenbankinhalten füllen Java Basics - Anfänger-Themen 6
W JTable mit einem JButton-Array füllen Java Basics - Anfänger-Themen 4
O JScrollPane zu gross für JTable Java Basics - Anfänger-Themen 2
L JTable Row selected -> fireTableDataChange do nothing. Java Basics - Anfänger-Themen 3
E JTable + TableModel updaten? Java Basics - Anfänger-Themen 1
O java.lang.IndexOutOfBoundsException JTable autoSort Java Basics - Anfänger-Themen 5
F JTable adding Row Java Basics - Anfänger-Themen 5
P jTable getColumnClass, mit unterschiedlichen Klassen in einer Column? Java Basics - Anfänger-Themen 5
M Eingabe in JTable bei Eingabe korrigieren Java Basics - Anfänger-Themen 2
Z jtable problem (das tausendste??) Java Basics - Anfänger-Themen 12
J JTable Java Basics - Anfänger-Themen 7
T JTable Java Basics - Anfänger-Themen 2
T JTable einzelne Zeilen löschen Java Basics - Anfänger-Themen 3
S Farbe eine Zeile in JTable ändern, wenn JButton geklickt wurd Java Basics - Anfänger-Themen 4
Uzi21 jTable / Inhalt speichern Java Basics - Anfänger-Themen 2
M Problem mit JTable und Model Java Basics - Anfänger-Themen 3
F Methoden JTable + 2 For-Schleifen Java Basics - Anfänger-Themen 4
C jtextfield und jtable Java Basics - Anfänger-Themen 34
X JTable mit Inhalten aus JTextField o.ä. füllen Java Basics - Anfänger-Themen 4
G JTable: SelectionListener Problem Java Basics - Anfänger-Themen 2
G JTable: Werte in Tabelle direkt ansprechen Java Basics - Anfänger-Themen 3
S Icons in JTable per ResultSet Java Basics - Anfänger-Themen 5
G Spalte in JTable unsichtbar machen, Zugriff auf Daten ermöglichen Java Basics - Anfänger-Themen 2
M Zelle von JTable mit Rahmen versehen Java Basics - Anfänger-Themen 4
G JTable: Inhalt einer selektierten Zeile speichern Java Basics - Anfänger-Themen 2
G JTable: mehrzeilige Zellen erstellen Java Basics - Anfänger-Themen 2
W Problem JTable Java Basics - Anfänger-Themen 5

Ähnliche Java Themen

Neue Themen


Oben