Diese Methode wird bei Änderungen meiner JTable aufgerufen:
UploadTableModel model = guiManager.getUploadTableModel();
// (...)
for (int i = 0; i < model.getRowCount(); i++) {
// (...)
// ******************************
// hier kommt eine Exception
AbloadFile ablFile = (AbloadFile) model.getValueAt(i,
UploadTableModel.COLUMN_URL);
// UploadTableModel.COLUMN_URL ist 2 (static final)
// ******************************
// (...)
}
// (...)
}```
In der im Code angegeben Zeile kommt folgende Exception:
Exception in thread “Thread-4” java.lang.ClassCastException: java.lang.String cannot be cast
to pcworld.fider.upload.abload.AbloadFile
at pcworld.fider.gui.MultiLinkCopyBox.updateLinkArea(MultiLinkCopyBox.java:119)
at pcworld.fider.gui.MultiLinkCopyBox$2.tableChanged(MultiLinkCopyBox.java:170)
at javax.swing.table.AbstractTableModel.fireTableChanged(Unknown Source)
at javax.swing.table.AbstractTableModel.fireTableCellUpdated(Unknown Source)
at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source)
at pcworld.fider.gui.UploadAction$1.run(UploadAction.java:115)
at java.lang.Thread.run(Unknown Source)
Und das, obwohl alle Values der Spalte UploadTableModel.COLUMN_URL (also Spalte 2) vom Typ AbloadFile sein müssten.
Hat jemand eine Ahnung, woran das liegen könnte?
Hier noch die Klasse UploadTableModel, mein TableModel:
```package pcworld.fider.gui.uploadTable;
import java.io.File;
import javax.swing.table.DefaultTableModel;
import pcworld.fider.gui.GUIManager;
import pcworld.fider.upload.UploadFile;
import pcworld.fider.upload.abload.AbloadFile;
public class UploadTableModel extends DefaultTableModel {
public static final int COLUMN_STATE = 0;
public static final int COLUMN_FILE = 1;
public static final int COLUMN_URL = 2;
public UploadTableModel(Object[] arg0, int arg1) {
super(arg0, arg1);
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
@Override
public Class<? extends Object> getColumnClass(int column) {
switch (column) {
case UploadTableModel.COLUMN_FILE:
return File.class;
case UploadTableModel.COLUMN_URL:
System.out.println(column + ": AbloadFile.class");
return AbloadFile.class;
default:
System.out.println(column + ": default - "
+ super.getColumnClass(column));
return super.getColumnClass(column);
}
}
public void addFile(File file) {
addRow(new Object[] { GUIManager.NOT_UPLOADED, file, null });
}
}```
Gruß,
pcworld
Wahrscheinlich hast Du die Zelle editiert. Der Editor hat dann einen String reingeschrieben. Vielleicht liegt das Problem aber auch woanders.
Erweitere mal zum Test Dein Tabellenmodell und schau Dir die Ausgaben genau an. Ggf. im Debugger da anhalten: @Override public void setValueAt(Object value, int row, int column) { System.out.printf("Adding %s::%s at %dx%d", value == null ? null : value.getClass(), value, column, row); System.out.println(); super.setValueAt(value, row, column); }
Grüße,
-Ebenius
Großes Dankeschön!
Das Problem war tatsächlich, dass ich bei setValueAt für diese Spalte einen String übergeben hatte, statt ein Objekt der Klasse AbloadFile :rolleyes: - könnte Java aber eigentlich eine Exception werfen, ich pflege ja nicht umsonst mein TableModel…
Ich habe jetzt noch ein kleines Problem:
Bevor ich diesen Fehler korrigiert habe, gab es auch Probleme bei der Renderung der Zelle. Jetzt wird wieder der gewünschte Wert angezeigt.
Aber wenn ich jetzt den Wert per - in die Zwischenablage kopiere, wird der Wert der Methode AbloadFile#toString (von mir nicht überschrieben) zurückgegeben: „pcworld.fider.upload.abload.AbloadFile@181ed9e“
Meine Frage: Wie geht das nochmal, seine eigene „CopyAction“ über getActionMap().put(„copy“, meineCopyAction) zu implementieren, welche Methoden muss ich von AbstractAction überschreiben?
Früher hatte ich den gleichen Wert, den mein TableCellRenderer zurückgibt, über AbloadFile#toString zurückgegeben. Das will ich aber nicht mehr, weil ich bei Renderer und Zwischenablage immer den gleichen Wert „returnen“ und somit möglichst flexibel sein will. Außerdem kann statt AbloadFile auch der Wert null sein. Der TableCellRenderer macht dann „-“ hin, und die CopyAction soll dasselbe machen.
Wie Ebenius oben schon tlw. erwähnt hat, lässt sich der Wert trotzdem noch über TableModel#setValueAt ändern. Nur per Doppelklick auf die Zelle öffnet sich kein Editor.
Du kannst auch einfach bei dem entsprechenden Beitrag auf „Zitieren“ klicken und dann den Java-Code aus dem BBCode-Quelltext rauskopieren.
Auf die Frage antworte ich mal nicht, weil sie Dein Problem nicht so sinnvoll löst. Copy & Paste wird per TransferHandler realisiert. Jeder Swing-Komponente kann man einen TransferHandler setzen. Normaler Weise kümmert sich darum das jeweilige UI-Delegate; im Falle der JTable also die BasicTableUI-Klasse. Diese setzt der Tabelle diesen TransferHandler:
/**
* Create a Transferable to use as the source for a data transfer.
*
* @param c The component holding the data to be transfered. This
* argument is provided to enable sharing of TransferHandlers by
* multiple components.
* @return The representation of the data to be transfered.
*
*/
protected Transferable createTransferable(JComponent c) {
if (c instanceof JTable) {
JTable table = (JTable) c;
int[] rows;
int[] cols;
if (!table.getRowSelectionAllowed() && !table.getColumnSelectionAllowed()) {
return null;
}
if (!table.getRowSelectionAllowed()) {
int rowCount = table.getRowCount();
rows = new int[rowCount];
for (int counter = 0; counter < rowCount; counter++) {
rows[counter] = counter;
}
} else {
rows = table.getSelectedRows();
}
if (!table.getColumnSelectionAllowed()) {
int colCount = table.getColumnCount();
cols = new int[colCount];
for (int counter = 0; counter < colCount; counter++) {
cols[counter] = counter;
}
} else {
cols = table.getSelectedColumns();
}
if (rows == null || cols == null || rows.length == 0 || cols.length == 0) {
return null;
}
StringBuffer plainBuf = new StringBuffer();
StringBuffer htmlBuf = new StringBuffer();
htmlBuf.append("<html>
<body>
<table>
");
for (int row = 0; row < rows.length; row++) {
htmlBuf.append("<tr>
");
for (int col = 0; col < cols.length; col++) {
Object obj = table.getValueAt(rows[row], cols[col]);
String val = ((obj == null) ? "" : obj.toString());
plainBuf.append(val + " ");
htmlBuf.append(" <td>" + val + "</td>
");
}
// we want a newline at the end of each line and not a tab
plainBuf.deleteCharAt(plainBuf.length() - 1).append("
");
htmlBuf.append("</tr>
");
}
// remove the last newline
plainBuf.deleteCharAt(plainBuf.length() - 1);
htmlBuf.append("</table>
</body>
</html>");
return new BasicTransferable(plainBuf.toString(), htmlBuf.toString());
}
return null;
}
public int getSourceActions(JComponent c) {
return COPY;
}
}```
Speichere Dir einfach den Quelltext als eigene TransferHandler-Klasse ab, modifiziere ihn nach Deinen Wünschen und füge ihn dann der Tabelle hinzu. Fertig.
Happy Hacking!
Ebenius
Das Problem gibt’s nur bei Byte-Welt und wäre demnach lösbar, ohne den zu benutzenden Browser vorzuschreiben, wenn die nötige Kompetenz vorhanden wäre.
Zitieren und dan kopieren, wie oben vorgeschlagen, wäre bestenfalls ein Workaround, ergibt aber bei mir dies:
1.
public void updateLinkArea() {
2.
UploadTableModel model = guiManager.getUploadTableModel();
3.
// (…)
4.
for (int i = 0; i < model.getRowCount(); i++) {
5.
// (…)
6.
// ******************************
7.
// hier kommt eine Exception
8.
AbloadFile ablFile = (AbloadFile) model.getValueAt(i,
9.
UploadTableModel.COLUMN_URL);
10.
// UploadTableModel.COLUMN_URL ist 2 (static final)
11.
// ******************************
12.
// (…)
13.
}
14.
// (…)
15.
}
Wozu die Nummerierung überhaupt gut ist, ausser um Probleme zu verursachen und Leute zu ärgern, ist mir schleierhaft. Schliesslich trägt sie nur äusserst wenig zum Informationsgehalt des Quellcodes bei, wenn überhaupt. Zeilennummern brauch ich jedenfalls so gut wie gar nicht beim Quellcode im Browser. Da zudem niemand die Kompetenzen zu haben scheint, um die dadurch verursachten Probleme zu lösen, lassen die klügeren unter den Foren die Nummerierung wohl lieber weg.
Ich habe mir jetzt mal die Klasse TableTransferHandler in Eclipse rauskopiert.
Allerdings kann mir Eclipse keinen Vorschlage machen, wo sich die Klasse BasicTransferable befinden könnte - wo kriege ich die her?: return new BasicTransferable(plainBuf.toString(), htmlBuf.toString());
Zur Zeilennummerierung:
Also ich finde sie schon praktisch. Wenn man auf „Zitieren“ klickt und nicht den WYSIWYG-Editor benutzt, kann man den Code ohne Probleme rauskopieren.
Man könnte auch ein JavaScript programmieren, welches die Nummerierung ein- und ausschaltet - so schwierig ist das auch wieder nicht. Falls sich da niemand drum kümmert, programmiere ich mir ein Greasemonkey-Script für den guten alten Firefox
CTRL+SHIFT+T, dann „BasicTransferable“ eintippen. Und schon zeigt Dir Eclipse die Klasse javax.swing.plaf.basic.BasicTransferable an. Die ist allerdings package-visible und damit kannst Du sie nicht so einfach benutzen. Wirst Dir dann also Dein eigenes Transferable bauen müssen.
Brauchst ne Eclipse-Schulung, oder? Click auf „Attach Source“. Und wähl dir den Quelltext aus Deinem JDK aus. Liegt direkt im JDK-Verzeichnis als src.zip. Wenn es da nicht liegt, dann hast Du kein Sun JDK (sondern beispielsweise nur das JRE) installiert. Das wäre dann zu ändern.
Noch was wegen der Zeilennummerierung: Ich habe für Mozilla Firefox gerade ein Script programmiert, welches die Zeilennummerierung hier in Byte-Welt ein- und ausschalten lässt. Alles weitere in diesem Thread: Java-Code-Copy ohne Zeilennummerierung
Jetzt funktioniert alles bestens (hoffe ich zumindest ;-))!
Wenn das value einer Tabellenzelle null ist, muss man das noch extra behandeln.
Das ist jetzt mein Code: TableTransferHandler (verändert) - BasicTransferable (nicht verändert, nur aus der JDK-Source rauskopiert)
[quote=Ebenius]Wie polemisch. Ich beziehe mich oft auf Zeilennummern im Quelltext. Compiler übrigens auch gern.
Ebenius[/quote]
Du hast recht.
(Ich sprach allerdings vom Browser und daß sogar große Java Foren dort keine Nummerierung haben, ganz sicher aus triftigen Gründen. Ich mach mir jedoch keine grossen Hoffnungen, daß das hier auch so gemacht wird, ist klar, wollte es nur mal gesagt haben. Glücklicherweise ist das Forum noch klein, so daß sein Nummerierungsproblem mich nur ab und zu ärgert. Vielleicht ist das Problem aber auch mit ein Grund, weshalb das Forum nicht schneller Zuwachs erhält. Sozusagen ein “Abschreckeffekt”.)