比较两个或多个 JTable 和“突出显示”差异

Posted

技术标签:

【中文标题】比较两个或多个 JTable 和“突出显示”差异【英文标题】:Compare two or more JTables and 'Highlight' differences 【发布时间】:2012-09-12 07:31:39 【问题描述】:

我正在构建一个摆动应用程序,它的左侧是项目列表,右侧是表格。右侧显示的表格数量取决于左侧选择的项目。我希望能够“突出显示”(setBackground)所有正在显示的表中相同的行。

我已经阅读了关于重写 prepareRenderer 或 getTableCellRendererComponent 的内容。然后,条件渲染逻辑位于 Overridden 方法中。

DefaultTableCellRenderer getTableCellRendererComponent never gets called http://tips4java.wordpress.com/2010/01/24/table-row-rendering/ http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#renderer

但据我所知和我的理解(如果我错了,请纠正我)这两个选项都不允许您在这个被覆盖的方法中同时比较两个不同的 JTable。 prepareRenderer 在扩展 JTable 的类中被覆盖,因此它在特定表上被实例化。然后,被覆盖的方法只会影响 Table 的特定实例。

public class CustomRenderer extends JTable 
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) 
    Component c = super.prepareRenderer(renderer, row, column);
    //  add custom rendering here
    return c;
;

...
CustomRenderer currTable = new CustomRenderer();

getTableCellRendererComponent 是通过特定 JTable 的 columnModel 中特定列的 setCellRenderer 设置的。

public class CustomRenderer extends DefaultTableCellRenderer 
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) 
    JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        if (isSelected) 
            l.setBackground(Color.gray);
        
        else 
            l.setBackground(Color.white);
        
    return l;
    ;

...
CustomRenderer cr = new CustomRenderer();
currTable.getcolumnModel().getColumn(1).setCellRenderer(cr);

那么我该怎么做呢

if(tableOne.getValueAt(1, 1).equals(tableTwo.getValueAt(1, 1) 
//set Cell 1,1 background(Color.blue)
else
//set Cell 1,1 background(Color.red)

现在我有一个非常丑陋的 hack,它使用多个表格单元格选择和一个 getTableCellRendererComponent 方法,该方法测试 isSelected 布尔值并相应地更改背景。现在这已经足够好了(因为我是唯一一个使用这个程序的人)但是必须有一种更好的方法能够根据不同表的条件或值同时比较和更改一个表的呈现。

或者我的问题可能是错误的?

提前感谢您的阅读/回复

【问题讨论】:

【参考方案1】:

我已经阅读了关于重写 prepareRenderer 或 getTableCellRendererComponent 的内容。然后,条件渲染逻辑位于 Overridden 方法中。但是从我所知道的和我所理解的(如果我错了,请纠正我),这两个选项都不允许您在这个被覆盖的方法中同时比较两个不同的 JTable。

你为什么这么说,你有什么数据来支持这个说法,因为它是错误的。

prepareRenderer 扩展了 JTable

一个方法不能扩展一个类,所以这没有意义。

所以它的重写方法只能访问 JTable 的特定实例,并且 getTableCellRendererComponent 是通过特定 JTable 的 columnModel 中特定列的 setCellRenderer 设置的。

方法可以访问程序员允许他们访问的任何内容。关键在于传递引用。

【讨论】:

我添加了示例代码、一些源代码和改写的部分。我知道 prepareRenderer 没有显式扩展 JTable,但是扩展 JTable 的类包含被覆盖的方法。您还可以澄清第一个引用块中的错误以及为什么?谢谢【参考方案2】:

使用SwingX 基础架构,就这么简单

实现一个 HighlightPredicate 来决定一个不是单元格是否应该被突出显示 实例化一个荧光笔(例如一个通过设置背景颜色进行装饰的 ColorHighlighter)并将其添加到两个表中 实现/注册一些侦听器,根据状态将谓词设置为荧光笔

下面是一个简短的 sn-p,它使用配置了列表中所选项目的 EqualsHighlightPredicate 来突出显示具有相同内容的所有单元格。享受吧!

final JXList list = new JXList(AncientSwingTeam.createNamedColorListModel());
JXTable table = new JXTable(new AncientSwingTeam());
final ColorHighlighter highlighter = new ColorHighlighter(
        HighlightPredicate.NEVER, Color.YELLOW, null);
list.addHighlighter(highlighter);
table.addHighlighter(highlighter);
ListSelectionListener l = new ListSelectionListener() 

    @Override
    public void valueChanged(ListSelectionEvent e) 
        if (e.getValueIsAdjusting()) return;
        highlighter.setHighlightPredicate(
                createPredicate(list.getSelectedValue()));
    

    private HighlightPredicate createPredicate(Object selectedValue) 
        if (selectedValue == null) return HighlightPredicate.NEVER;
        return new HighlightPredicate.EqualsHighlightPredicate(selectedValue);
    
;
list.getSelectionModel().addListSelectionListener(l);

【讨论】:

在其他答案中,我最喜欢这个。花了一段时间,但我终于想出了如何让表格比较在突出显示方面起作用。我必须说 JXTable 的文档很少,但它似乎运行良好。谢谢【参考方案3】:

我可能会使用某种“突出显示模型”,它能够确定哪些表中的哪些行应该突出显示(以及如何突出显示)。

然后,您要么直接将其提供给单元格渲染器,要么直接在单元格渲染器中从表格中提取它(不过,这假定表格的类型正确,并打开一整罐蠕虫)。

所以基本上你最终可能会得到类似......

public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) 
    // Seed the component with the default values
    super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    // You may need to change the value of the component to reflect what
    // you want to display here

    // It should be noted, that this method will override the selection
    // highlighting, you may want to check isSelected and make
    // your own decisions over what needs to be done.
    HighlightModel model = getHighlightModel();
    // You should check for null
    Color color = model.getHighlightBackgroundFor(table, row);
    if (color != null) 
        setOpaque(true);
        setBackground(color);
    

    return this; // Assuming you've used a component as a base renderer ;)


【讨论】:

这是一个“HighlightModel”,还是一个带有额外逻辑以允许检查突出显示颜色的 TableModel?只是好奇 好吧,这取决于你。我可能会从定义对其调用的方法的接口开始,然后实现无关紧要 这是有道理的。经常发现自己在实现某种 TableModel,所以最近与 JTable 相关的所有内容对我来说都像是钉子。 @Panky 这会是一个带有额外逻辑的 TableModel 绝对不是 - 它是一个使用数据的纯视觉装饰。很好(偏向于我 :-) 在 SwingX 中分离:您可以将逻辑放入 HighlightPredicate 并使用该谓词配置 Highlighter

以上是关于比较两个或多个 JTable 和“突出显示”差异的主要内容,如果未能解决你的问题,请参考以下文章

Excel 公式或规则或 vba 比较 2 个单元格并仅突出显示差异

如何改进 git 的差异突出显示?

比较两个 HTML 源并显示视觉差异 [关闭]

“突出显示” JTable 中的特定行

突出显示 JTable 的列标题

并排输出两个Pandas数据帧的差异 - 突出显示差异