简体   繁体   English

JTable 保持颜色与 model 不排

[英]JTable keep color with the model not the row

I have a dilemma.我有一个难题。 I am writing a program that will view logs from an application and depending on the log level (eg Info, Debug, Error, etc.) the row gets highlighted a certain color.我正在编写一个程序,它将查看来自应用程序的日志,并根据日志级别(例如信息、调试、错误等),该行以某种颜色突出显示。 I also give the users the ability to hide log levels.我还让用户能够隐藏日志级别。 So if the clicks off "show info", then all the log entries that are "Info" are hidden.因此,如果单击“显示信息”,则所有“信息”的日志条目都将被隐藏。 The problem comes that when entries are hidden, the color they were highlighted gets pushed down to the row that was below them.问题来了,当条目被隐藏时,它们被突出显示的颜色被推到它们下面的行。

I am looking for a way that the color stays with the entry and not render the color in the next cell when the object is hidden我正在寻找一种在隐藏 object 时颜色与条目保持一致而不在下一个单元格中呈现颜色的方法

Here is what I have done thus far:这是我到目前为止所做的:

I initialize the renderer and set it as the default:我初始化渲染器并将其设置为默认值:

tableRenderer = new ModelTableRenderer();
table.setDefaultRenderer(Object.class, tableRenderer);

and then I create my sorter:然后我创建我的分拣机:

sorter = new TableRowSorter<DefaultTableModel>(model);
table.setRowSorter(sorter);

and I have a callback method that each of checkboxes use called showSelected .我有一个回调方法,每个复选框都使用名为showSelected This takes a list of LogLevels to show and applies the filter to the sorter:这需要一个 LogLevels 列表来显示并将过滤器应用于排序器:

  public void showSelected(List<LogLevel> showList) {
    Set<LogLevel> hideSet = showList.stream().collect(Collectors.toSet());
    sorter.setRowFilter(new RowFilter<DefaultTableModel, Object>(){

      @Override
      public boolean include(Entry<? extends DefaultTableModel, ? extends Object> entry) {
        LogLevel level = (LogLevel) entry.getValue(LogModel.ERROR_COLUMN);
        return hideSet.contains(level);
      }
    });
  }

ModelTableRenderer class ModelTableRenderer class

This class is what I use to render the row colors.这个 class 是我用来渲染行 colors 的。 It looks at the current row and grabs the column value where the LogLevel exists and depending on what the log level is.它查看当前行并获取LogLevel所在的列值,具体取决于日志级别。 This works fine when rows are not hidden.当行没有隐藏时,这很好用。

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;
  }
}

This is the results with no filters.这是没有过滤器的结果。 All the rows are highlighted correctly所有行都正确突出显示无过滤器

but when I click off "show trace" we can see now the first row is highlighted grey when it still should be green但是当我单击“显示跟踪”时,我们现在可以看到第一行是灰色的,而它仍然应该是绿色的

应用过滤器

Both components (highlighting and hiding) work on their own as intended but coupling them together has been a challenge.两个组件(突出显示和隐藏)都按预期独立工作,但将它们耦合在一起一直是一个挑战。 Any help would be great.任何帮助都会很棒。

The age old problem with JTables... a view index is not a model index. JTables 的老问题......视图索引不是 model 索引。 Do not use a view index to lookup in the model and vice versa.不要使用视图索引在 model 中查找,反之亦然。

Look up JTable.convertRowIndexToView , JTable.convertRowIndexToModel , JTable.convertColumnIndexToView and JTable.convertColumnIndexToModel . Look up JTable.convertRowIndexToView , JTable.convertRowIndexToModel , JTable.convertColumnIndexToView and JTable.convertColumnIndexToModel .

The indexes received in the renderer are view indexes.在渲染器中接收到的索引是视图索引。 You are using the view index received to lookup in the model.您正在使用收到的视图索引在 model 中进行查找。 Use the proper "convert" method first to convert to a model index, before looking up in the model.在查找 model 之前,首先使用正确的“转换”方法转换为 model 索引。

Thanks to TT's suggestion i was able to fix the problem.感谢 TT 的建议,我能够解决问题。 I changed my renderer to:我将渲染器更改为:

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;
  }
}

I also added a tableModelRenderer to render the suppression when the user clicks on the checkbox.我还添加了一个tableModelRenderer以在用户单击复选框时呈现抑制。 Since this is the only value that changes, we can call repaint on that由于这是唯一改变的值,我们可以调用 repaint

model.addTableModelListener(new TableModelListener() {

  @Override
  public void tableChanged(TableModelEvent e) {
    table.repaint();
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM