JTable-Zelle mittels JFileChooser befüllen

  • Themenstarter Themenstarter Touby
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
T

Touby

Gast
Hallo zusammen,

ich zerbreche mir schon seit längerem dem Kopf darüber, wie ich folgendes Problem lösen kann und komme hauptsächlich wegen dem ganzen Interface-Wirrwar bei JTables und CellEditor etc. durcheinander.

Und zwar möchte ich eine JTable erstellen in der u.a. in einer Spalte jeweils ein Pfad auf eine Datei hinterlegt werden soll. Die Zellen dieser Spalte sollen editierbar sein, allerdings so, dass sich ein JFileChooser öffnet wenn man einen Doppelklick auf der Zelle ausführt und der gewählte Dateipfad sich in die Zelle einträgt sobald man die Auswahl getroffen hat. Es soll kein einfaches "String-Editing" wie bei einer Standard-String-Zelle möglich sein.

Ich dachte, dass sowas vielleicht mit einem eigenen CellEditor möglich ist, aber selbst da bin ich mir noch so sicher. Damit ich also den Zellen mit den Dateipfaden prinzipiell einen eigenen Editor zuweisen kann habe ich für den Anfang schonmal eine Wrapper-Klasse namens FilePath erstellt, die einfach erstmal ganz banal einen String kapselt der einen Pfad repräsentieren soll:

Code:
package wos.models;

public class FilePath {

	private String filePath;
	
	public FilePath(String filePath) {
		this.filePath = filePath;
	}

	public String getFilePath() {
		return filePath;
	}

	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}

	@Override
	public String toString() {
		return filePath;
	}
	
}

Mit der folgenden Zeile (xmlTable ist meine JTable) kann ich jetzt den JTable-Feldern, die Instanzen von FilePath beinhalten, nachweislich erfolgreich einen eigenen Editor zuweisen:

Code:
xmlTable.setDefaultEditor(FilePath.class, new FileTableCellEditor());

Allerdings fängt es jetzt schon an, dass ich keine Ahnung habe, wie ich die FileTableCellEditor-Klasse implementieren muss bzw. ob es auf diesem Wege überhaupt funktioniert. Denn ein CellEditor liefert meinem Verständnis nach ja im wesentlichen eine Komponente zurück, die dann für die Dauer des Editing in die Zelle eingefügt wird (also zum Beispiel ein JTextField mit dem alten Wert), aber gerade das will ich ja nicht, denn das Editing soll ja komplett von der Auswahl mittels eines JFileChooser abgefangen werden.

Kann mit da jemand weiterhelfen?
 
Hallo,

grundsätzlich sei hier schon mal auf das Tutorial hier in den FAQ verwiesen.

Zum konkreten Problem: Man könnte z.B einen JButton als Editorelement verwenden. ActionListener drauf und von da aus den JFileChooser öffnen.
 
Michael... hat gesagt.:
Hallo,

grundsätzlich sei hier schon mal auf das Tutorial hier in den FAQ verwiesen.

Zum konkreten Problem: Man könnte z.B einen JButton als Editorelement verwenden. ActionListener drauf und von da aus den JFileChooser öffnen.

Danke schonmal für den Hinweis auf die Tutorials. Ich bin jetzt zumindest schonmal so weit, dass ich glaube, dass ein angepasster TableCellEditor nicht das ist, was ich brauche, da der ja scheinbar immer temporär den Inhalt der Zelle mit einem Swing-Element ersetzt, das editierbar ist (also zum Beispiel einem JTextField oder einem JSpinner oder...). Gerade das will ich verhindern, ich brauche ja temporär die Zelle nicht durch einen Editor ersetzen, sondern eben nur einen FileChooser öffnen und dessen Dateipfad dann in die Zelle einsetzen.

Die Lösung mit dem Button wäre mir ein Schritt zuviel: Doppelklick auf Zelle -> Button erscheint -> FileChooser öffnet sich. Den Schritt mit dem Button braucht man ja nicht unbedingt. Außerdem habe ich grundsätzlich das Problem, wie ich innerhalb des eines Editors sagen kann, dass er fertig ist mit editieren... Denke auch, dass das gar nicht geht, da er nur auf Befehle von außen reagiert über die ganzen implementierten Interfaces. Aber irgendetwas muss ja wissen, dass meine Eingabe fertig ist (also zum Beispiel RETURN bei einem JTextField). Keine Ahnung, wo das gesendet oder festgelegt wird. Glaube einfach, dass Editoren nicht für das gemacht sind, was ich vorhabe.

Habe jetzt einen neuen Lösungsansatz versucht, der prinzipiell ganz vielversprechend scheint. Und zwar kann eine JTable mit setValueAt(Object aValue, int row, int column) direkt einen Wert setzen, auch wenn er von der GUI aus nicht editierbar ist mit einem TableCellEditor, also z.B. auf diese Weise:

Code:
xmlTable.setValueAt(new FilePath("Gesetzter Wert"), 0, 6);

Ich weiß jetzt nur nicht, wie ich an die Componenten komme, die in der JTable die einzelnen Zellen darstellen um jeweils einen Listener auf z.B. MouseEvents zu registrieren. Dann kann ich beispielsweise auf Doppelklick etwas ähnliches wie die obige Zeile ausführen, nachdem zuvor ein JFileChooser den gewünschten Pfad abgefragt hat.

Ich bräuchte also JTable-Methode in der Art Component getComponentAt(int row, int column), kann sowas aber nicht finden. Gibt's da vielleicht ne andere Möglichkeit?
 
Das mit dem Button verstehe ich eher so.
Du ahst zwei Spalten, in der einen ist das Feld, in dem der Pfad steht, im anderen Ein Button, der beim Klicken einen Filechooser öffnest.

Ich habe sowas mal geschrieben. Wenn du dich bis heute Abend / Nacht gedulden kannst, dann kann ich es mal raussuchen und posten.

Beides geht aber über einen eigenen CellEditor und Renderer.


Nicht getestete ALTERNATIVE!
-Füge der Table einen MousListener hinzu.
-Bei der methode clicked. Überprüfst ob es ein Linksklick war und speicherst den timestamp.
-Davor fragst du jedoch ab, ob der letzte Klick auch ein Linkslick war und wann er geschah. Ist der Unterschied zwischen den Timestamps z.B. kleiner 1 sek. dann soll er einen Filechooser öffnen, welcher dann den Wert in die selektierte Zelle des tabels schreibt. Must hier noch abfragen,. ob überhaupt ne Zelle selektiert wurde und er nicht auf dem Rahmen rumgeklickt hat.

Sollte theorethisch funktionieren. Ohne CellRenderer, CellEditor und Knöpfe! 😎
 
MHH, hast ja meine ungetestete Alternative bei dir am schluss erläutert. habe ich erst danach kapiert.

Es gibt eine Methode, die getSelectedCell() heißt. Weis jetzt nur nicht ob du die über das Tabel oder das Model der Tabel kriegst.

Damit solltest du dein letztes Problem lösen könne.
 
Vielen Dank für Deine Tipps, ich habe mich mit deren Hilfe soweit durchwursteln können um das Problem zu lösen. Und zwar habe ich zunächst meiner JTable (hier xmlTable) einen MouseListener hinzugefügt:

Code:
xmlTable.addMouseListener(new FileChooserMouseAdapter());

Der MouseListener ist als innere Klasse meiner JFrame-Hauptanwendung realisiert und sieht folgendermaßen aus:

Code:
class FileChooserMouseAdapter extends MouseAdapter {
	
    @Override
    public void mouseClicked(MouseEvent e) {
        
        // Nur auf Doppelklick reagieren
        if (e.getClickCount() == 2) {
            
            // Die Position der gerade ausgewählten Zelle ermitteln, denn dort muss auch der Doppelklick erfolgt sein
            int colNum = xmlTable.getSelectedColumn();
            int rowNum = xmlTable.getSelectedRow();
            
            // Nur reagieren, wenn auf eine Zelle in der siebten Spalte geklickt wurde
            if (colNum == 6) {
                
                // FileChooser erstellen
                JFileChooser fileChooser = new JFileChooser();
                // In currentDirectory merke ich mir in der umgebenden Klasse, welches Verzeichnis zuletzt benutzt wurde, um dieses für die
                // nächste Auswahl wieder anzubieten. Standardmäßig ist es null, was dem Home-Verzeichnis entspricht.
                fileChooser.setCurrentDirectory(currentDirectory);
                int returnVal = fileChooser.showOpenDialog(WallOfSoundBank.this);
                
                // Nur Änderungen vornehmen, wenn der Dialog nicht abgebrochen wurde
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    // Die ausgewählte Datei ermitteln
                    File selectedFile = fileChooser.getSelectedFile();
                    String selectedFilePath = selectedFile.getAbsolutePath();
                    // Die JTable-Zelle, auf die geklickt wurde, mit dem Pfad der ausgewählten Datei befüllen
                    xmlTable.setValueAt(new FilePath(selectedFilePath), rowNum, 6);
                    // Das für diese Auswahl benutzte Verzeichnis merken
                    currentDirectory = (selectedFile.isDirectory()) ? selectedFile.getParentFile() : selectedFile.getAbsoluteFile();
                    // Die JTable neu zeichnen um die Änderungen zu sehen
                    xmlTable.repaint();
                }
                
            }
            
        }
        
    }
	
}

Die von Dir erwähnte Funktion getSelectedCell() gibt es leider nicht, aber das Zusammenspiel aus getSelectedColumn() und getSelectedRow() funktioniert genauso gut. Vielen Dank für die Anregungen!
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben