TreeTable exportieren/importieren

KlaRo

Mitglied
Schönen guten Tag an die Community,

ich würde gerne eine TreeTable (Swing) in eine Datei (XML, CSV, whatever) exportieren und selbige wieder importieren. Sinn des Ganzen ist ich lese viele Dateien und einige deren Infos aus und gebe alles in einer JTreeTable aus. Um dies nicht ständig aufs Neue tun zu müssen, was recht zeitintensiv ist, würde ich gerne die Daten aus der JTreeTable in eine Datei – Format spielt eigentlich keine Rolle – exportieren/importieren.

Bisher habe ich leider nur den Export/Import von JTrees oder JTables gefunden, allerdings leider nicht von der Kombination aus beiden. Hat ev. dazu jemand eine Lösung, Codebeispiel, Link? Der Export von dem Tree oder dem Table einzeln klappt einwandfrei.

Wäre super, wenn mir jemand helfen könnte!

Viele Grüße aus dem verschneiten Süden Deutschlands...
 

mihe7

Top Contributor
Sinn des Ganzen ist ich lese viele Dateien und einige deren Infos aus und gebe alles in einer JTreeTable aus. Um dies nicht ständig aufs Neue tun zu müssen,

Warum gehst Du nicht einfach her und machst die Vorverarbeitung in einem separaten Schritt, speicherst das Ergebnis und liest von dort in Dein Model für die TreeTable ein?
 

mihe7

Top Contributor
Wie meinst Du das genau?

Sagen wir mal, Du hättest eine CSV-Datei mit 1 Mio. Zeilen und 200 Spalten. Für die Anzeige brauchst Du davon aber nur 100.000 Zeilen und 5 Spalten. Dann transformierst Du die Datei halt vorab derart, so dass sie nur noch das enthält, was Du anzeigen willst, was dann zu einer neuen CSV-Datei mit eben 100.000 Zeilen und 5 Spalten führt. Diese neue Datei verwendest Du dann zum Einlesen. Dazu musst Du nicht die TreeTable exportieren.
 

KlaRo

Mitglied
Ja OK das Exportieren habe ich auf diese Weise bereits in eine CSV-Datei realisiert. Allerdings schaffe ich es leider nicht diese Daten wieder in die TreeTable zu importieren.

Meine Frage ist nun, wie kann ich diese Daten aus der CSV-Datei wieder in die TreeTable importieren?

Die Daten in der CSV-Datei sind wie folgt aufgebaut:
Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis1-4/Verzeichnis1-5/Dateiname1;Info 1;Info 2;Info 3;Info 4
Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis1-4/Verzeichnis1-5/Dateiname2;Info 1;Info 2;Info 3;Info 4
Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis1-4/Verzeichnis2-5/Dateiname1;Info 1;Info 2;Info 3;Info 4
Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis1-4/Verzeichnis2-5/Dateiname2;Info 1;Info 2;Info 3;Info 4
Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis2-4/Verzeichnis1-5/Dateiname1;Info 1;Info 2;Info 3;Info 4
was dann in der Treetable wie folgt nach dem Einlesen aussehen soll:
Verzeichnis1-3
-Verzeichnis1-4
--Verzeichnis1-5
---Dateiname1;Info 1;Info 2;Info 3;Info 4
---Dateiname2;Info 1;Info 2;Info 3;Info 4
--Verzeichnis2-5
---Dateiname1;Info 1;Info 2;Info 3;Info 4
---Dateiname2;Info 1;Info 2;Info 3;Info 4
-Verzeichnis2-4
--Verzeichnis1-5
---Dateiname1;Info 1;Info 2;Info 3;Info 4
---Dateiname2;Info 1;Info 2;Info 3;Info 4

Oder gibt es gar eine einfachere/elegantere Lösung z.B. mittels XML-Datei oder so?
 

mihe7

Top Contributor
Naja, Du liest halt die Daten ein und baust das Model auf. Die erste Spalte ist offensichtlich der Pfad zum Knoten. Mit XML/JSON kannst Du die Baumstruktur direkt in der Datei abbilden, das ändert aber am Vorgehen nicht wirklich was: dann liest Du halt das XML/JSON ein und baust das Model auf :)

EDIT: Was für eine JTreeTable-Implementierung verwendest Du eigentlich?
 

KlaRo

Mitglied
Ich steh wohl etwas auf dem Schlauch oder ich bin zu doof 😖 was heißt »Baumstruktur direkt in der Datei abbilden«? In welcher Datei?

Die JTreeTable-Implementierung wird mittels SWING realisiert.
 

lam_tr

Top Contributor
Leider kenne ich mich viel zu wenig mit Swing aus, aber in JavaFX kann man die Werte Zelle für Zelle eines TreeTableView auslesen und in eine Datei schreiben, siehe https://stackoverflow.com/questions...table-treetable-view-content-to-pdf-and-excel.

Code habe ich rauskopiert. Jede Zeile vom Baum wird durchiteriert und Zelle für Zelle geholt.

Java:
int rowIndex = treeTableView.getRow(treeRowItem);
for(int i=0;i<treeTable.getColumns();i++){
    TreeTableColumn ttc = treeTable.getColumns().get(i);
    String value = ttc.getCellData(rowIndex).toString();
}

Ich denke das wird auch für Swing gehen nur etwas komlizierter :)
 

KlaRo

Mitglied
Leider kenne ich mich viel zu wenig mit Swing aus, aber in JavaFX kann man die Werte Zelle für Zelle eines TreeTableView auslesen und in eine Datei schreiben, siehe https://stackoverflow.com/questions...table-treetable-view-content-to-pdf-and-excel.

Code habe ich rauskopiert. Jede Zeile vom Baum wird durchiteriert und Zelle für Zelle geholt.

Java:
int rowIndex = treeTableView.getRow(treeRowItem);
for(int i=0;i<treeTable.getColumns();i++){
    TreeTableColumn ttc = treeTable.getColumns().get(i);
    String value = ttc.getCellData(rowIndex).toString();
}

Ich denke das wird auch für Swing gehen nur etwas komlizierter :)
Danke für Deine Antwort. Das Exportieren der TreeTable-Daten in die CSV-Datei ist bereits implementiert und funktioniert einwandfrei mit der oben geschilderten Struktur. Mein Problem ist es, nun die Daten aus dieser erstellten CSV-Datei wieder in die TreeTable zu importieren → das bekomme ich iwie nicht hin.
 

lam_tr

Top Contributor
Danke für Deine Antwort. Das Exportieren der TreeTable-Daten in die CSV-Datei ist bereits implementiert und funktioniert einwandfrei mit der oben geschilderten Struktur. Mein Problem ist es, nun die Daten aus dieser erstellten CSV-Datei wieder in die TreeTable zu importieren → das bekomme ich iwie nicht hin.
Wie bildest du die das Modell als CSV? Hast du kein pedant zu dem Einlesen?
 

mihe7

Top Contributor
was heißt »Baumstruktur direkt in der Datei abbilden«? In welcher Datei?
Mit CSV schreibst Du ja eine Tabellenstruktur, mit XML oder JSON kannst Du Hierarchien abbilden. Beispielhaft:
XML:
<laufwerk>
  <Verzeichnis1-1>
    <Verzeichnis1-2>
      <Dateiname1 />
    </Verzeichnis1-2>
  </Verzeichnis1-1>
  <Verzeichnis2-1>
  ...
</laufwerk>
Das entspricht also im Wesentlichen Deinem Baum, nur ändert das am Problem des Einlesens nichts bzw. kaum etwas.

Die JTreeTable-Implementierung wird mittels SWING realisiert.
Das ist schon klar, aber welche Implementierung hast Du verwendet? JTreeTable ist ja keine Standardkomponente.
 

KlaRo

Mitglied
Wird mit folgender Klasse bewerkstelligt:
Java:
public class JTreeTable extends JTable {
    protected static TreeTableCellRenderer tree;

    public JTreeTable(TreeTableModel treeTableModel) {
        super();

        // Create the tree. It will be used as a renderer and editor.
        tree = new TreeTableCellRenderer(treeTableModel);

        // Install a tableModel representing the visible rows in the tree.
        super.setModel(new TreeTableModelAdapter(treeTableModel, getTree()));

        // Force the JTable and JTree to share their row selection models.
        getTree().setSelectionModel(new DefaultTreeSelectionModel() {
            private static final long serialVersionUID = -2566509625314303370L;

            // Extend the implementation of the constructor, as if:
            /* public this() */ {
                setSelectionModel(listSelectionModel);
            }
        });
        // Make the tree and table row heights the same.
        getTree().setRowHeight(getRowHeight());

        // Root aus- oder einblenden
        getTree().setRootVisible(true);

        // Install the tree editor renderer and editor.
        setDefaultRenderer(TreeTableModel.class, getTree());
        setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());

        setShowGrid(true);// Tabellenlinien anzeigen
        setIntercellSpacing(new Dimension(0, 0));
    }

    /*
     * Workaround for BasicTableUI anomaly. Make sure the UI never tries to paint
     * the editor. The UI currently uses different techniques to paint the renderers
     * and editors and overriding setBounds() below is not the right thing to do for
     * an editor. Returning -1 for the editing row in this case, ensures the editor
     * is never painted.
     */
    public int getEditingRow() {
        return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 : editingRow;
    }

    public static TreeTableCellRenderer getTree() {
        return tree;
    }

    // The renderer used to display the tree nodes, a JTree.
    public class TreeTableCellRenderer extends JTree implements TableCellRenderer {
        private static final long serialVersionUID = -5593454246676923763L;
        protected int visibleRow;

        public TreeTableCellRenderer(TreeModel model) {
            super(model);
        }

        public void setBounds(int x, int y, int w, int h) {
            super.setBounds(x, 0, w, JTreeTable.this.getHeight());
        }

        public void paint(Graphics g) {
            g.translate(0, -visibleRow * getRowHeight());
            super.paint(g);
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {
            if (isSelected) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }

            setToolTipText("Doppelklick auf eine Datei zum Öffnen");

            visibleRow = row;
            return this;
        }
    }

    // The editor used to interact with tree nodes, a JTree.
    public class TreeTableCellEditor extends AbstractCellEditor implements TableCellEditor {
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int r, int c) {
            return getTree();
        }
    }
}
 

KlaRo

Mitglied
Wie bildest du die das Modell als CSV? Hast du kein pedant zu dem Einlesen?
Das Erstellen der CSV-Datei wird mit dieser Klasse erledigt:
Java:
public class WriteCSVfile {
    public static void writeCSVfile(JTreeTable dtm, String fileName, char customSeparator)
            throws IOException, ClassNotFoundException, SQLException {
        int nRow = dtm.getRowCount();
        int nCol = dtm.getColumnCount();

        int startWithCol = 0;

        int pfadCol = 0;

        Writer writer = null;

        try {
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), PROPERTIES_CHARSET));

            // Stand bei Erstellung der Datei
            LocalDate dateNow = LocalDate.now();
            String dateFormatted = dateNow.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            writer.write(dateFormatted + SYS_LINE_SEP);

            // ausgewählter Haupt-Pfad
            writer.write(MusicGui.lblHeader.getText().replace(TITLE_TEXT + " — ", "") + SYS_LINE_SEP);

            // ausgelesene Dateien
            writer.write(MusicGui.lblAnzahlDatsGes.getText() + CUSTOM_SEPARATOR + MusicGui.lblAnzDats.getText()
                    + SYS_LINE_SEP);

            // write header information
            StringBuffer bufferHeader = new StringBuffer();
            for (int j = startWithCol; j < nCol; j++) {
                // Tabellennummer mit Pfad ermitteln
                if (dtm.getColumnName(j).equals(strPfad)) {
                    pfadCol = j;
                }

                // Wert zu Ausgabestring hinzufügen
                bufferHeader.append(dtm.getColumnName(j));
                if (j < nCol - 1) {
                    bufferHeader.append(customSeparator);
                }
            }
            writer.write(bufferHeader.toString() + SYS_LINE_SEP);

            // write row information, ohne TreeView, da keine Daten davon
            // ausgegeben werden
            for (int i = 0; i < nRow; i++) {
                StringBuffer buffer = new StringBuffer();
                for (int j = startWithCol; j < nCol; j++) {
                    buffer.append(dtm.getValueAt(i, j));
                    if (j < nCol - 1) {
                        buffer.append(customSeparator);
                    }
                }

                // Ausgabe, wenn Wert in Spalte für Pfad nicht Null
                if (dtm.getValueAt(i, pfadCol) != null) {
                    writer.write(buffer.toString() + SYS_LINE_SEP);
                }
            }
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}
 

KlaRo

Mitglied
Wie schaut TreeTableModel aus?
TreeTableModel ist ein Interface und schaut folgendermaßen aus:
Java:
public interface TreeTableModel extends TreeModel {
    /**
     * Returns the number of available column.
     */
    public int getColumnCount();

    /**
     * Returns the name for column number <code>column</code>.
     */
    public String getColumnName(int column);

    /**
     * Returns the type for column number <code>column</code>.
     */
    @SuppressWarnings("rawtypes")
    public Class getColumnClass(int column);

    /**
     * Returns the value to be displayed for node <code>node</code>, at column
     * number <code>column</code>.
     */
    public Object getValueAt(Object node, int column);

    /**
     * Indicates whether the the value for node <code>node</code>, at column number
     * <code>column</code> is editable.
     */
    public boolean isCellEditable(Object node, int column);

    /**
     * Sets the value for node <code>node</code>, at column number
     * <code>column</code>.
     */
    public void setValueAt(Object aValue, Object node, int column);
}
 

mihe7

Top Contributor
Sorry, hatte vergessen. Du brauchst eine Klasse, die Deine Dateien bzw. Verzeichnisse beschreibt. Nennen wir sie mal FileDescriptor. Diese hat ein paar Attribute (Namen und was Du sonst in der Tabelle anzeigen willst) und Kinder, die wiederum FileDescriptor-Objekte sind. Damit baust Du einen Baum auf, wobei der erste FileDescriptor Dein root ist. Den Pfad durch den Baum entnimmst Du eben der ersten Spalte.
 

mihe7

Top Contributor
In etwa so:
Java:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeSet;
import java.util.stream.Collectors;
public class FileDescriptor {
           
    public enum Type {
        FILE, DIRECTORY
    };
    private static final Comparator<FileDescriptor> byName = 
            Comparator.comparing(FileDescriptor::getName);
    
    private final String name;
    private final Type type;
    private final TreeSet<FileDescriptor> children = new TreeSet<>(byName);
    private final List<String> infos = new ArrayList<>();
    FileDescriptor() {
        this("", Type.DIRECTORY);
    }
    FileDescriptor(String name, Type type) {
        this.name = name;
        this.type = type;
    }
    String getName() {
        return name;
    }
    void add(FileDescriptor child) {
        children.add(child);
    }
    void addInfo(String info) {
        infos.add(info);
    }
    Set<FileDescriptor> getChildren() {
        return Collections.unmodifiableSet(children);
    }
    FileDescriptor findChildByName(String name) {
        FileDescriptor query = new FileDescriptor(name, Type.DIRECTORY);
        FileDescriptor candidate = children.ceiling(query);
        if (candidate != null && byName.compare(candidate, query) == 0) {
            return candidate;
        }
        return null;
    }
    FileDescriptor getOrCreateFile(String[] path) {
        FileDescriptor currentDir = this;
        for (int i = 0; i < path.length; i++) {
            FileDescriptor child = currentDir.findChildByName(path[i]);
            if (child == null) {
                Type type = i < path.length-1 ? Type.DIRECTORY : Type.FILE;
                child = new FileDescriptor(path[i], type);
                currentDir.add(child);
            }
            currentDir = child;
        }
        return currentDir;
    }
    @Override
    public String toString() {
        return String.join(": ", name, infos.stream().collect(Collectors.joining("|")));
    }
}

Zum Test:
Java:
import java.io.BufferedReader;
import java.io.StringReader;
public class Test {
    static final String CONTENT = "Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis1-4/Verzeichnis1-5/Dateiname1;Info 1;Info 2;Info 3;Info 4\n"
            + "Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis1-4/Verzeichnis1-5/Dateiname2;Info 1;Info 2;Info 3;Info 4\n"
            + "Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis1-4/Verzeichnis2-5/Dateiname1;Info 1;Info 2;Info 3;Info 4\n"
            + "Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis1-4/Verzeichnis2-5/Dateiname2;Info 1;Info 2;Info 3;Info 4\n"
            + "Laufwerk/Verzeichnis1-1/Verzeichnis1-2/Verzeichnis1-3/Verzeichnis2-4/Verzeichnis1-5/Dateiname1;Info 1;Info 2;Info 3;Info 4";
    public static void main(String[] args) throws Exception {
        FileDescriptor root = new FileDescriptor();
        new BufferedReader(new StringReader(CONTENT)).lines()
            .forEach(l -> readLine(root, l));
        print(root, 0);
    }
    private static void print(FileDescriptor root, int level) {
        if (root == null) {
            return;
        }
        System.out.printf("%" + (level+1) + "s%s\n", "", root.toString());
        for (FileDescriptor child : root.getChildren()) {
            print(child, level+1);
        }
    }
    private static void readLine(FileDescriptor root, String line) {
        String[] parts = line.split(";");
        String[] path = parts[0].split("/");
        FileDescriptor d = root.getOrCreateFile(path);
        for (int i = 1; i < parts.length; i++) {
            d.addInfo(parts[i]);
        }
    }
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
K Swing Struktur für TreeTable rekursiv aufbauen AWT, Swing, JavaFX & SWT 17
N JavaFX TreeTable Scene Builder AWT, Swing, JavaFX & SWT 8
A Suche TreeTable-Komponente AWT, Swing, JavaFX & SWT 12
M treetable einfaches beispiel gesucht AWT, Swing, JavaFX & SWT 6
C Problem mit TreeTable AWT, Swing, JavaFX & SWT 8
L JavaFX IntelliJ Standalone Programm exportieren AWT, Swing, JavaFX & SWT 9
VPChief Swing Eclipse: Nach Exportieren, Button funktioniert nicht mehr AWT, Swing, JavaFX & SWT 26
VPChief Eclipse: Projekt mit src ordner exportieren. AWT, Swing, JavaFX & SWT 76
L JavaFX OpenJFX13 Anwendung exportieren AWT, Swing, JavaFX & SWT 7
R Bilddatei exportieren AWT, Swing, JavaFX & SWT 0
B Pong Projekt mit LWJGL Klassen exportieren AWT, Swing, JavaFX & SWT 14
M 3D-Grafik Java3D-Application als executable .jar exportieren (Eclipse) AWT, Swing, JavaFX & SWT 5
I exportieren mit ressourcen? AWT, Swing, JavaFX & SWT 4
D SWT-Programm in JAR-Paket exportieren AWT, Swing, JavaFX & SWT 6
P SWT, eclipse , exportieren , JAR AWT, Swing, JavaFX & SWT 7
M Swing Tabellendaten exportieren AWT, Swing, JavaFX & SWT 11
L JTable nach Excel exportieren AWT, Swing, JavaFX & SWT 2
A Nach HTML exportieren AWT, Swing, JavaFX & SWT 4
S Kann javafx.scene.layout.VBoxBuilder nicht importieren AWT, Swing, JavaFX & SWT 3
L JavaFX CSS in ein anderes CSS importieren AWT, Swing, JavaFX & SWT 2
S Swing Wie JXTable importieren AWT, Swing, JavaFX & SWT 2
J SWT in eclipse importieren AWT, Swing, JavaFX & SWT 11
J Java bild in andere Klasse importieren AWT, Swing, JavaFX & SWT 5
J Bild importieren - TetrisStein AWT, Swing, JavaFX & SWT 4
J Swing Datenbank in ein Swingfenster importieren? AWT, Swing, JavaFX & SWT 13
B JTextPane und Image importieren in HTML String. AWT, Swing, JavaFX & SWT 2
F Externes Look & Feel für Swing wie importieren/verwenden AWT, Swing, JavaFX & SWT 3
W netbeans projekt in Eclipse importieren -gui teil geht nicht AWT, Swing, JavaFX & SWT 5
K Text in JTable importieren AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen


Oben