在表示 Color 对象时为 JTable 中的单个单元格着色
Coloring a single cell in a JTable when representing Color objects
我有一个 JTable,用于在不同的行中显示大量不同的数据类型。只有两列,其中左列是变量名称,右列是与变量关联的变量(因此使用 ColumnModel 不适合我的解决方案)。到目前为止,这对于基元来说效果非常好,而且 JComboBox 和 JCheckBox 的 DefaultRenderer 效果很好。
我现在正尝试将 java.awt.Color 整合到 table 中,但我希望它经过渲染,以便单元格实际上填充了颜色,只是没有文本(我不知道当我达到那个点时,我相信那会很困难)。到目前为止,我已经完成了单元的功能;单击单元格会弹出一个 JColorChooser 和 returns 颜色,然后它将应用于与该单元格关联的对象。我为此使用的代码是:
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());
我的ColorRendererclass如下:
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 上的教程我认为相当有用,但最终并没有像我希望的那样工作。这个论坛上的其他问题已经接近适用于我的情况,但往往缺乏适用于特定对象类型的关键要素,而不仅仅是特定的单元格。如果我要在我的 table 中存储大量 Color 对象,我希望它们都以相同的方式运行。
如果我的实施中有明显的错误或遗漏,如果能指出这一点就太好了。仔细查看代码(在发布之前我已经重读了很多次以确保我包含了所有内容),我相信问题可能出在我的行 class 中。它包含一个名为 getValue() 的方法,该方法将 return 对象,因此从技术上讲,我可以这样调用:
if(rowObject.getValue() instanceof Color)
//Apply renderer
但是我如何使用为特定 class 设置默认渲染器的代码来做到这一点?
您必须覆盖表模型中的方法 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();
}
}
不知道这是否是最好的方法,但覆盖 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)
似乎只适用于列上的单元格渲染器,所以如果您只想以不同方式渲染单个单元格,那就不太好了。
我见过的另一种选择是定义一个单元格渲染器,将其应用于列,并在单元格渲染器的 getTableCellRendererComponent(...)
函数中确定这是哪种数据类型以及是否渲染它或将其传递到另一个渲染器。
就我个人而言,我更喜欢第一个选项,但如果您要渲染大量不同的自定义单元格类型,并且希望将所有渲染代码集中在一个 class 中,那么我可以看到第二个选项的吸引力。
我有一个 JTable,用于在不同的行中显示大量不同的数据类型。只有两列,其中左列是变量名称,右列是与变量关联的变量(因此使用 ColumnModel 不适合我的解决方案)。到目前为止,这对于基元来说效果非常好,而且 JComboBox 和 JCheckBox 的 DefaultRenderer 效果很好。
我现在正尝试将 java.awt.Color 整合到 table 中,但我希望它经过渲染,以便单元格实际上填充了颜色,只是没有文本(我不知道当我达到那个点时,我相信那会很困难)。到目前为止,我已经完成了单元的功能;单击单元格会弹出一个 JColorChooser 和 returns 颜色,然后它将应用于与该单元格关联的对象。我为此使用的代码是:
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());
我的ColorRendererclass如下:
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 上的教程我认为相当有用,但最终并没有像我希望的那样工作。这个论坛上的其他问题已经接近适用于我的情况,但往往缺乏适用于特定对象类型的关键要素,而不仅仅是特定的单元格。如果我要在我的 table 中存储大量 Color 对象,我希望它们都以相同的方式运行。
如果我的实施中有明显的错误或遗漏,如果能指出这一点就太好了。仔细查看代码(在发布之前我已经重读了很多次以确保我包含了所有内容),我相信问题可能出在我的行 class 中。它包含一个名为 getValue() 的方法,该方法将 return 对象,因此从技术上讲,我可以这样调用:
if(rowObject.getValue() instanceof Color)
//Apply renderer
但是我如何使用为特定 class 设置默认渲染器的代码来做到这一点?
您必须覆盖表模型中的方法 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();
}
}
不知道这是否是最好的方法,但覆盖 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)
似乎只适用于列上的单元格渲染器,所以如果您只想以不同方式渲染单个单元格,那就不太好了。
我见过的另一种选择是定义一个单元格渲染器,将其应用于列,并在单元格渲染器的 getTableCellRendererComponent(...)
函数中确定这是哪种数据类型以及是否渲染它或将其传递到另一个渲染器。
就我个人而言,我更喜欢第一个选项,但如果您要渲染大量不同的自定义单元格类型,并且希望将所有渲染代码集中在一个 class 中,那么我可以看到第二个选项的吸引力。