我有一个JTable,用于在不同的行中显示多种不同的数据类型。只有两列,其中左列是变量名称,右列是与变量关联的变量(因此使用ColumnModel不适合我的解决方案)。到目前为止,这对于原语来说非常有效,而JComboBox和JCheckBox的DefaultRenderer运行良好。
我现在正在尝试将java.awt.Color集成到表中,但是我希望它被渲染以便单元格实际上填充了Color,并且根本没有文本(我不相信这会很难当我到达那一点时。到目前为止,我已经完成了单元格的功能;单击单元格会弹出一个JColorChooser并返回Color,然后将其应用于与单元格关联的对象。我正在使用的代码是:
JTable table = new JTable(new CustomModel(columnNames, values))
{
//Other functions inside here are excluded to keep it concise
public void changeSelection(int row, int col, boolean toggle, boolean extend)
{
/*Row is a custom object I am using for each row in the table. Its purpose is to
hold more information about the rows than I would normally be able to. Suffice
to say for this example, it will be returning something with a Color in it*/
Row obj = ((CustomModel)(table.getModel())).getRow(row);
/*ObjectProperties is essentially a modified version of a hashmap that also
stores the objects type among other things*/
if(obj.getType() == ObjectProperties.TYPE.COLOR)
{
Color newColor = JColorChooser.showDialog(null, "Pick color", Color.RED);
if(newColor != null)
{
table.getModel().setValueAt(newColor, row, col);
}
}
super.changeSelection(row, col, toggle, extend);
}
}
所以这似乎很好用,但现在用于渲染。我想如果我尝试设置DefaultRenderer,它会工作,所以我使用了行:
table.setDefaultRenderer(Color.class, new ColorRenderer());
我的ColorRenderer类如下:
public class ColorRenderer extends JLabel implements TableCellRenderer
{
public ColorRenderer()
{
setOpaque(true);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
{
Color newColor = (Color)value;
setBackground(newColor);
return this;
}
}
当我使用它时,我没有运气显示实际的颜色,而是我得到了颜色的字符串表示(我认为这意味着我的渲染器根本不工作)。所以我还没有真正让它呈现正确的方式,更不用说能够在用户选择新的东西时更改显示的颜色。
我一直在努力让CustomRenderer工作很长一段时间,我已经查看了我可以得到的所有资源。我认为Oracle's JTable section的教程非常有用,但最终并没有像我希望的那样有用。围绕这个论坛的其他问题已经接近适用于我的情况,但往往缺乏应用于特定对象类型的关键元素,而不仅仅是特定的单元格。如果我在表格中存储了大量的Color对象,理想情况下我会喜欢它们的行为方式相同。
如果我的实施中存在明显的错误或缺失,那么指出这一点真是太棒了。仔细查看代码(我在发布之前已经多次重读,以确保我已经包含了所有内容),我相信问题可能出在我的Row类中。它包含一个名为getValue()的方法,它将返回对象,所以在技术上我可以调用类似的东西:
if(rowObject.getValue() instanceof Color)
//Apply renderer
但是我怎么能用为特定类设置默认渲染器的代码呢?
答案 0 :(得分:1)
不知道这是否是最佳方式,但覆盖getCellRenderer(int row, int col)
可能会对您有所帮助:
public TableCellRenderer getCellRenderer(int row, int col){
//Only care about the first column
if(col == 1){
Row obj = ((CustomModel)(table.getModel())).getRow(row);
//Check to see if this is a color
if(obj.getType() == ObjectProperties.TYPE.COLOUR){
return super.getDefaultRenderer(Color.class);
}
}
//Either this wasn't a color or it wasn't the first column, either way its super.getCellRenderer's problem now
return super.getCellRenderer(row, col);
}
getCellRenderer(int row, int col)
似乎只适用于列上的单元格渲染器位置,因此如果您只想以不同方式渲染单个单元格,则不会太好。
我看到的另一个替代方法是定义一个单元格渲染器,将其应用于collumn并在单元格渲染器的getTableCellRendererComponent(...)
函数中确定这是哪种数据类型以及是否渲染它或传递它另一个渲染器。
就我个人而言,我更喜欢第一个选项,但是如果您有大量不同的自定义单元格类型要渲染并希望将所有渲染代码保存在一个类中,那么我可以看到第二个选项的吸引力。
答案 1 :(得分:0)
你必须覆盖tablemodel中的方法getColumnClass(int c)
(最好使用DefaultTableModel ...)
class MyTableModel extends AbstractTableModel {
private String[] columnNames = ...//same as before...
private Object[][] data = ...//same as before...
//taken from http://docs.oracle.com/javase/tutorial/uiswing/components/table.html
public Object getValueAt(int row, int col) {
return data[row][col];
}
public Class getColumnClass(int c) {
//here - check that the proper class is returned!
return getValueAt(0, c).getClass();
}
}