我一直在研究JTables,并且已经找到了一些很好的资源来解释如何为列设置CellRenderer和CellEditor,但是发现尝试设置单个单元格的渲染器和编辑器的可能性稍差。
我的表的一般想法是有两列,其中左列显示变量名称,右列允许修改相关变量。我已经能够执行验证的大多数单元格,甚至找到了如何以我需要的方式使用DefaultCellRenderer和DefaultCellEditor,但尝试使用我正在努力的自定义渲染器和编辑器。下面我试着说明我的设计下的表格看起来如何: (左手值是变量名,右手是值)
x 0
y 0
isDestructable [复选框]
图像[可点击的单元格]
图像值应允许用户单击该单元格,然后将调出JFileChooser,并提取响应并在单元格内呈现String表示形式。我写了很多代码片段,但是尝试将它们链接在一起就是我真正迷失的部分。下面我提供了迄今为止与这些功能相关的代码:
/*
Code that creates the table and passes a custom model to it. Code for setting the other
types of renderers and editors I have already got working have been omitted
*/
table = new JTable(new MyDataModel(columnNames, values))
{
public TableCellRenderer getCellRenderer(int row, int col)
{
if(col == 1)
{
if(table.getModel().getValueAt(row, 0).equals("image"))
{
//This is where I would want to set my renderer I believe
}
}
return super.getCellRenderer(row, col);
}
public TableCellEditor getCellEditor(int row, int col)
{
if(col == 1)
{
if(table.getModel().getValueAt(row, 0).equals("image"))
{
//This is where I would want to set my editor I believe
}
}
return super.getCellEditor(row, col);
}
};
/*
As an inner class, I have created the following editor that should display a JFileChooser
when the user clicks on the cell
*/
private class ButtonTableCellEditor extends AbstractTableCellEditor implements TableCellEditor
{
private JFrame mainframe;
private JFileChooser jfc;
public ButtonTableCellEditor(JFrame frame)
{
mainframe = frame;
jfc = new JFileChooser();
}
@Override
public void addCellEditorListener(CellEditorListener arg0)
{
}
@Override
public void cancelCellEditing()
{
//Hide the JFileChooser here
super.cancelCellEditing();
}
@Override
public Object getCellEditorValue()
{
//Here we need to return the filename that has been returned by the JFileChooser
return "test";
}
@Override
public boolean isCellEditable(EventObject arg0)
{
return true;
}
@Override
public void removeCellEditorListener(CellEditorListener arg0)
{
//Not sure that I will actually need to use this at all
}
@Override
public boolean shouldSelectCell(EventObject arg0)
{
int returned = jfc.showOpenDialog(mainFrame);
if(returned == JFileChooser.APPROVE_OPTION)
{
System.out.println("File was fine");
}
else
{
stopCellEditing();
}
return true;
}
public boolean stopCellEditing()
{
return false;
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean arg2, int row, int col)
{
//This is something I know that is incredibly important based off other examples, but
//I am unsure what to do in here in my case
return null;
}
}
所有我真的需要帮助(我认为)是将ButtonTableCellEditor与我需要的单个单元格链接(条件是左手栏等于"图像",以及如何处理getTableCellEditorComponent(在我的情况下。任何帮助都会非常感激,我现在已经被困了一段时间。
此外,这是我的第一个问题(我已经阅读了很多问题,并试图尽可能多地注意),所以如果我提出问题的方式有任何反馈,以便以后的问题可能会更好结构化,这将是最受欢迎的。谢谢大家!
答案 0 :(得分:0)
基于Intercept JTable Selection ChangeEvents中提供的答案,以及MadProgrammer调查ListSelectionListeners的极其有用的方向,我已经能够提出以下解决方案:
table = new JTable(new CustomModel(columnNames, values))
{
/*
I have omitted the other functions I have overridden here as they are not necessary for the
solution*/
@Override
public void changeSelection(int row, int col, boolean toggle, boolean extend)
{
if(col == 1 && table.getModel().getValueAt(row, 0).equals("image"))
{
/*
imageChooser is the name of the JFileChooser I am using, and I am passing the
main frame of my application to centre the window that appears
*/
int returned = imageChooser.showOpenDialog(frame);
if(returned == JFileChooser.APPROVE_OPTION)
table.getModel().setValueAt(imageChooser.getSelectedFile().getName(), row, col);
}
super.changeSelection(row, col, toggle, extend);
}
}
我不相信这个解决方案具有很高的可扩展性,但出于我的程序的目的,它的效果非常好。只要单击了适当的单元格,我就已成功打开JFileChooser,并且单元格内的String将更改为表示所选文件的名称。
单元格本质上充当按钮而不会呈现为一个按钮。根据UI外观要求,这可能并不总是合适的,因为它看起来像普通的表格单元格,可能会导致可用性问题。
编辑:
一种更具伸缩性的方法是使用类似“instanceof”的方法确定第1列中值的类型,因为这将适用于该类型的所有对象。