【问题标题】:jTable, overwritten DefaultCellRenderer won't redraw icons after sortjTable,覆盖的 DefaultCellRenderer 在排序后不会重绘图标
【发布时间】:2012-10-05 23:32:49
【问题描述】:

我在使用 jTableDefaultTableModel 时遇到问题。

我有两列使用覆盖的DefaultTableCellRenderer 显示图标:

private static ImageIcon errorIcon = new ImageIcon("workDir/icons/error.png");
private static ImageIcon pageIcon = new ImageIcon("workDir/icons/page_white.png");
private static ImageIcon serverIcon = new ImageIcon("workDir/icons/server_go.png");
private static ImageIcon acceptIcon = new ImageIcon("workDir/icons/accept.png");

private class ImageRenderer extends DefaultTableCellRenderer {  

    JLabel lbl = new JLabel();

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

        //lbl.setText((String) value);
        lbl.setVerticalAlignment(SwingConstants.CENTER);
        lbl.setHorizontalAlignment(SwingConstants.CENTER);

        if (value.equals("e")) {
            lbl.setIcon(pageIcon);
            return lbl;
        }

        ServiceTicket t = TICKET_DICT.get((UUID) tableModel.getValueAt(row, 3));

        if (t == null) {
            throw new IllegalStateException("Cannot find Ticket for UUID");
        }

        if (t.getReport().getElsterCode().equals("0")) {
            if (t.getSendMode().equals(EricSendMode.VALIDATE_LOCALLY)) {
                lbl.setIcon(acceptIcon);
            } else {
                lbl.setIcon(serverIcon);
            }
        } else {
            lbl.setIcon(errorIcon);
        }

        lbl.repaint();
        return lbl;
    }
}

我在视图的初始化阶段设置了ImageRenderer

    resultTable.getColumnModel().getColumn(0).setCellRenderer(new ImageRenderer());
    resultTable.getColumnModel().getColumn(4).setCellRenderer(new ImageRenderer());

我希望我的表是可排序的。所以我使用这一行来启用默认排序:

resultTable.setAutoCreateRowSorter(true);

我现在的问题是排序工作正常,但第 0 列和第 4 列中的图标在排序事件后没有重绘。

我尝试添加一个事件来告诉表格单元格值已更改,但这不起作用:

    resultTable.getRowSorter().addRowSorterListener(
            new RowSorterListener() {

                @Override
                public void sorterChanged(RowSorterEvent e) {                        
                    if (e.getType().equals(RowSorterEvent.Type.SORTED)) {
                        for (int i = 0; i < tableModel.getRowCount(); i++) {
                            tableModel.fireTableCellUpdated(i, 0);
                            tableModel.fireTableCellUpdated(i, 4);
                        }
                    }

                }
            });

你能帮我在表格排序后重新绘制图标吗?我检查了表格模型,所有单元格和列都正确排序。甚至单元格中的值也会呈现为图标。

谢谢!

【问题讨论】:

  • 永远不会甚至考虑代表模型触发事件:行为良好的实现必须在适当的时候触发它们。更糟糕的是:在 sorterListener 中这样做很可能会产生无限循环......
  • 是的,你是对的,谢谢!我在另一种方法中产生了 StackOverFlowExceptions!

标签: java swing sorting jtable imageicon


【解决方案1】:

有些评论不是真正的答案,但评论太长了。

ServiceTicket t = TICKET_DICT.get((UUID) tableModel.getValueAt(row, 3));

在对表进行排序时,将从TableModel 中检索到不正确的值。此时,传递的row 索引与模型中索引row 处的元素不匹配(由于排序)。

使用JTable#convertRowIndexToModel 将索引转换为模型索引。

另外,当分拣机改变时调用fireTableCellUpdated的监听器是不需要的,甚至是不正确的。虽然表格可能会更改元素的显示顺序,但基础数据并未发生任何变化。

最后

我检查了表格模型,所有单元格和列都正确排序。甚至单元格中的值都呈现为图标

不确定您所说的“检查表模​​型”是什么意思。排序时,TableModel 没有任何变化。排序只发生在视图端,而不是模型端。

【讨论】:

  • 排序后的事件触发代码是不必要的 ehhh ...这是完全错误的(知道:-)
  • @kleopatra 我改写了那句话。希望现在更清楚了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-20
  • 1970-01-01
  • 2019-12-27
  • 2014-09-08
  • 2014-03-17
  • 1970-01-01
相关资源
最近更新 更多