java - What is the proper separation of responsibilities between TableCellRenderer and TableModel when using JTables? -
i working on part of application displays tables statistical data video files represented class frameinfo. after had table model including formatting, refactored other extreme , had table model return frameinfo instance each row , let cellrenderer decide field render , how each column. great nice things switching display of e.g. timecode values between ticks, seconds or timecodes ("00:01:02:03") repaint. happy until copied , pasted table contents gdocs spreadsheet , noticed got output of tostring() of model objects in cells (which logical when started thinking not want).
my options, far can see them now:
1) put model
pros: have in clipboard displayed, when copy
cons: - means triggering model events when switching display mode of timecodes - writing highlighters (i using jxtables btw.) become messy again, have string matching, can use model objects
2) leave , build custom copy action uses renderer , extracts text rendered label
pros: - table code stays clean
cons: - amount of work(?) - stuff rounded number lose accuracy
3) put dynamic stuff (timecodes) model , timecodes in renderer , live fact not wysiwyg copy & paste columns
pros & cons: - more or less half-assed compromise
any advice or maybe exiting code use, anyone?
thanks time!
extending on @trashgod's answer: option 1 plain wrong :-) tablemodel must contain data, nothing else. it's renderer's exclusive job present data in table (in fact, in of swing's collection views). , it's transferhandler's job export data in reasonable form, preferably same string representation renderer.
jxtable makes particularly easy share string representation between collaborators: small coin produce textual content called stringvalue, internal renderers configured. once configured, string used across string-related extended functionality, searching, sorting, regex-based filtering, , table's api:
string text = table.getstringat(row, column);
which allows custom transferhandler base string-building on:
/** * tabletransferable uses jxtable string api build * exported data. * * c&p basictableui, replaced tostring * table.getstringat(row, col) */ public static class xtabletransferhandler extends transferhandler { /** * create transferable use source data transfer. * * @param c component holding data transfered. * argument provided enable sharing of transferhandlers * multiple components. * @return representation of data transfered. * */ @override protected transferable createtransferable(jcomponent c) { if (!(c instanceof jxtable)) return null; jxtable table = (jxtable) c; int[] rows; int[] cols; if (!table.getrowselectionallowed() && !table.getcolumnselectionallowed()) { return null; } if (!table.getrowselectionallowed()) { int rowcount = table.getrowcount(); rows = new int[rowcount]; (int counter = 0; counter < rowcount; counter++) { rows[counter] = counter; } } else { rows = table.getselectedrows(); } if (!table.getcolumnselectionallowed()) { int colcount = table.getcolumncount(); cols = new int[colcount]; (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>\n<body>\n<table>\n"); (int row = 0; row < rows.length; row++) { htmlbuf.append("<tr>\n"); (int col = 0; col < cols.length; col++) { // original: // object obj = table.getvalueat(rows[row], cols[col]); // string val = ((obj == null) ? "" : obj.tostring()); // replaced jxtable api: string val = table.getstringat(row, col); plainbuf.append(val + "\t"); htmlbuf.append(" <td>" + val + "</td>\n"); } // want newline @ end of each line , not tab plainbuf.deletecharat(plainbuf.length() - 1).append("\n"); htmlbuf.append("</tr>\n"); } // remove last newline plainbuf.deletecharat(plainbuf.length() - 1); htmlbuf.append("</table>\n</body>\n</html>"); return new basictransferable(plainbuf.tostring(), htmlbuf.tostring()); } @override public int getsourceactions(jcomponent c) { return copy; } }
example of usage:
defaulttablemodel model = new defaulttablemodel( new string[]{"action"}, 0); jxtable table = new jxtable(model); object[] keys = table.getactionmap().allkeys(); (object key : keys) { model.addrow(new object[]{table.getactionmap().get(key)}); } stringvalue sv = new stringvalue() { @override public string getstring(object value) { if (value instanceof action) { return (string) ((action) value).getvalue(action.name); } return stringvalues.to_string.getstring(value); } }; table.getcolumn(0).setcellrenderer(new defaulttablerenderer(sv)); table.setdragenabled(true); table.settransferhandler(new xtabletransferhandler());
Comments
Post a Comment