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

Popular posts from this blog

html5 - What is breaking my page when printing? -

c# - must be a non-abstract type with a public parameterless constructor in redis -

ajax - PHP/JSON Login script (Twitter style) not setting sessions -