gpt4 book ai didi

java - 使用 JTables 时,TableCellRenderer 和 TableModel 之间职责的正确分离是什么?

转载 作者:行者123 更新时间:2023-11-29 07:55:49 24 4
gpt4 key购买 nike

我正在开发一个应用程序的一部分,该应用程序显示表格,其中包含有关由 FrameInfo 类表示的视频文件的统计数据。现在,在我最初只有一个可以执行所有操作(包括一些格式化)的表模型之后,我将其重构到另一个极端,让表模型只为每一行返回 FrameInfo 实例,然后让 CellRenderer 决定要呈现的字段以及如何呈现每个字段柱子。这很棒,因为我可以做一些不错的事情,比如切换显示。刻度、秒或时间码(“00:01:02:03”)之间的时间码值仅通过重绘。我很高兴,直到我将表格内容复制并粘贴到 gdocs 电子表格中,并注意到我只得到了所有单元格中模型对象的 toString() 的输出(当我开始考虑它时这是合乎逻辑的,但显然不是我想要的) .

我的选择,据我所知:

1) 把所有东西放回模型中

优点:当我复制时,我会在剪贴板中显示所有内容

缺点:- 表示切换时间码显示模式时触发模型事件- 编写荧光笔(顺便说一句,我正在使用 JXTables。)会再次变得困惑,因为我必须进行字符串匹配,现在我可以在其中使用我的模型对象

2) 保持原样并构建一个使用渲染器的自定义复制操作,然后从渲染标签中提取文本

优点:- 表代码保持干净

缺点:- 工作量(?)- 对于四舍五入之类的东西,我会失去准确性

3) 将除动态内容(时间码)之外的所有内容都放入模型中,并在渲染器中执行时间码,并接受这样一个事实,即我没有获得用于复制和粘贴这些列的所见即所得

优点和缺点:- 或多或少的半途而废的妥协

有任何建议或者我可以使用的现有代码吗?

感谢您的宝贵时间!

最佳答案

扩展@trashgod 的回答:选项 1 是完全错误的:-) TableModel 必须包含数据,没有别的。在表格中显示数据(事实上,在任何 Swing 的 Collection View 中)是渲染器的专有工作。以合理的形式导出数据是 TransferHandler 的工作,最好使用与渲染器相同的字符串表示形式。

JXTable 使得在协作者之间共享字符串表示变得特别容易:生成文本内容的小硬币称为 StringValue,所有内部渲染器都使用它进行配置。配置后,该字符串将用于所有与字符串相关的扩展功能,例如搜索、排序、基于正则表达式的过滤和表的 api:

String text = table.getStringAt(row, column);

它允许自定义 TransferHandler 将其字符串构建基于:

/**
* A TableTransferable that uses JXTable string api to build
* the exported data.
*
* C&p from BasicTableUI, replaced toString with
* table.getStringAt(row, col)
*/
public static class XTableTransferHandler extends 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.
*
*/
@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];
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>\n<body>\n<table>\n");

for (int row = 0; row < rows.length; row++) {
htmlBuf.append("<tr>\n");
for (int col = 0; col < cols.length; col++) {
// original:
// Object obj = table.getValueAt(rows[row], cols[col]);
// String val = ((obj == null) ? "" : obj.toString());
// replaced by JXTable api:
String val = table.getStringAt(row, col);
plainBuf.append(val + "\t");
htmlBuf.append(" <td>" + val + "</td>\n");
}
// we want a newline at the end of each line and not a tab
plainBuf.deleteCharAt(plainBuf.length() - 1).append("\n");
htmlBuf.append("</tr>\n");
}

// remove the 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;
}

}

使用示例:

DefaultTableModel model = new DefaultTableModel(
new String[]{"Action"}, 0);
JXTable table = new JXTable(model);
Object[] keys = table.getActionMap().allKeys();
for (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());

关于java - 使用 JTables 时,TableCellRenderer 和 TableModel 之间职责的正确分离是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17773894/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com