Java JTable根据模型而不是行保持颜色
我左右为难。我正在编写一个程序,该程序将查看应用程序中的日志,并根据日志级别(例如,信息、调试、错误等)以特定颜色突出显示行。我还为用户提供了隐藏日志级别的功能。因此,如果单击“show info”,那么所有属于“info”的日志条目都将被隐藏。问题在于,当条目被隐藏时,它们高亮显示的颜色会被下推到它们下面的行 我正在寻找一种方法,当对象被隐藏时,颜色与条目保持一致,而不在下一个单元格中渲染颜色 以下是我迄今为止所做的工作: 我初始化渲染器并将其设置为默认值:Java JTable根据模型而不是行保持颜色,java,swing,jtable,Java,Swing,Jtable,我左右为难。我正在编写一个程序,该程序将查看应用程序中的日志,并根据日志级别(例如,信息、调试、错误等)以特定颜色突出显示行。我还为用户提供了隐藏日志级别的功能。因此,如果单击“show info”,那么所有属于“info”的日志条目都将被隐藏。问题在于,当条目被隐藏时,它们高亮显示的颜色会被下推到它们下面的行 我正在寻找一种方法,当对象被隐藏时,颜色与条目保持一致,而不在下一个单元格中渲染颜色 以下是我迄今为止所做的工作: 我初始化渲染器并将其设置为默认值: tableRenderer = n
tableRenderer = new ModelTableRenderer();
table.setDefaultRenderer(Object.class, tableRenderer);
然后我创建我的分类器:
sorter = new TableRowSorter<DefaultTableModel>(model);
table.setRowSorter(sorter);
ModelTableRenderer类
这个类是我用来渲染行颜色的。它查看当前行并获取存在LogLevel
的列值,具体取决于日志级别。当行未隐藏时,此操作可以正常工作
public class ModelTableRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 425091150909034479L;
public ModelTableRenderer() { }
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (!c.isVisible()) return c;
Color color = Color.WHITE;
LogLevel level = (LogLevel) table.getModel().getValueAt(row, LogModel.ERROR_COLUMN);
switch (level) {
case DEBUG:
color = Color.GREEN;
break;
case ERROR:
color = Color.ORANGE;
break;
case FATAL:
color = Color.RED;
break;
case INFO:
color = Color.WHITE;
break;
case TRACE:
color = Color.GRAY;
break;
case WARN:
color = Color.YELLOW;
break;
default:
break;
}
if ((Boolean)table.getModel().getValueAt(row, LogModel.SUPPRESS_COLUMN)) {
color = Color.BLACK;
}
c.setBackground(color);
c.setForeground(Color.BLACK);
table.repaint();
return c;
}
}
这是没有过滤器的结果。所有行都正确高亮显示
但当我点击关闭“显示跟踪”时,我们现在可以看到第一行高亮显示为灰色,而它仍然应该为绿色
这两个组件(突出显示和隐藏)都按预期独立工作,但将它们耦合在一起一直是一个挑战。任何帮助都会很好。JTables的老问题。。。视图索引不是模型索引。不要使用视图索引在模型中查找,反之亦然 抬头看,然后
渲染器中接收的索引是视图索引。您正在使用收到的视图索引在模型中查找。在模型中查找之前,首先使用适当的“转换”方法转换为模型索引。JTables的老问题。。。视图索引不是模型索引。不要使用视图索引在模型中查找,反之亦然 抬头看,然后
渲染器中接收的索引是视图索引。您正在使用收到的视图索引在模型中查找。在查找模型之前,首先使用适当的“转换”方法转换为模型索引。由于TT的建议,我能够解决问题。我将渲染器更改为:
public class ModelTableRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 425091150909034479L;
public ModelTableRenderer() { }
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
int modelRow = table.convertRowIndexToModel(row);
int modelCol = table.convertRowIndexToModel(column);
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, modelRow, modelCol);
Color color = Color.WHITE;
LogLevel level = (LogLevel) table.getModel().getValueAt(modelRow, LogModel.ERROR_COLUMN);
switch (level) {
case DEBUG:
color = Color.GREEN;
break;
case ERROR:
color = Color.ORANGE;
break;
case FATAL:
color = Color.RED;
break;
case INFO:
color = Color.WHITE;
break;
case TRACE:
color = Color.GRAY;
break;
case WARN:
color = Color.YELLOW;
break;
default:
break;
}
if ((Boolean)table.getModel().getValueAt(modelRow, LogModel.SUPPRESS_COLUMN)) {
color = Color.BLACK;
}
c.setBackground(color);
c.setForeground(Color.BLACK);
return c;
}
}
我还添加了一个tableModelRenderer
,以便在用户单击复选框时呈现抑制效果。因为这是唯一更改的值,所以我们可以在该值上调用repaint
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
table.repaint();
}
});
多亏了TT的建议,我才解决了这个问题。我将渲染器更改为:
public class ModelTableRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 425091150909034479L;
public ModelTableRenderer() { }
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
int modelRow = table.convertRowIndexToModel(row);
int modelCol = table.convertRowIndexToModel(column);
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, modelRow, modelCol);
Color color = Color.WHITE;
LogLevel level = (LogLevel) table.getModel().getValueAt(modelRow, LogModel.ERROR_COLUMN);
switch (level) {
case DEBUG:
color = Color.GREEN;
break;
case ERROR:
color = Color.ORANGE;
break;
case FATAL:
color = Color.RED;
break;
case INFO:
color = Color.WHITE;
break;
case TRACE:
color = Color.GRAY;
break;
case WARN:
color = Color.YELLOW;
break;
default:
break;
}
if ((Boolean)table.getModel().getValueAt(modelRow, LogModel.SUPPRESS_COLUMN)) {
color = Color.BLACK;
}
c.setBackground(color);
c.setForeground(Color.BLACK);
return c;
}
}
我还添加了一个tableModelRenderer
,以便在用户单击复选框时呈现抑制效果。因为这是唯一更改的值,所以我们可以在该值上调用repaint
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
table.repaint();
}
});
1.不要在渲染器中调用repaint()。2.不知道为什么需要“isVisible()”检查。该表将仅呈现可见的行。3.你可能想退房。它允许您轻松地为整行着色,即使每列的数据类型不同。重新绘制是我能够在单击某行时使其变黑的唯一方法。这是错误的。想想看。你调用repaint(),它调用渲染器,它调用repaint(),它调用渲染器……我意识到了这一点,并试图想出一个更好的解决方案。有什么建议吗?当您单击按钮时,应该在表上调用repaint()。1。不要在渲染器中调用repaint()。2.不知道为什么需要“isVisible()”检查。该表将仅呈现可见的行。3.你可能想退房。它允许您轻松地为整行着色,即使每列的数据类型不同。重新绘制是我能够在单击某行时使其变黑的唯一方法。这是错误的。想想看。你调用repaint(),它调用渲染器,它调用repaint(),它调用渲染器……我意识到了这一点,并试图想出一个更好的解决方案。有什么建议吗?当您单击按钮时,您应该在表上调用repaint()。我还添加了一个tableModelRenderer来渲染-为什么?我理解你的逻辑,你点击一个按钮来过滤表格。重置RowFilter应该足以导致表自身重新绘制()。如果没有,那么您应该能够在复选框的ActionListener中调用repaint()。如果这不起作用,那么我建议您做一些非常奇怪的事情。这是针对表本身中的复选框。不是过滤器。它是用于抑制列以屏蔽行的。我还添加了一个tableModelRenderer来渲染-为什么?我理解你的逻辑,你点击一个按钮来过滤表格。重置RowFilter应该足以导致表自身重新绘制()。如果没有,那么您应该能够在复选框的ActionListener中调用repaint()。如果这不起作用,那么我建议您做一些非常奇怪的事情。这是针对表本身中的复选框。不是过滤器。它用于抑制列以遮住行。