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

每当一个单元格的内容与用户的输入匹配时,我想突出显示JTable中的特定行。 以下代码是我迄今为止所做的工作:

JTable table = new JTable(model) { public Component prepareRenderer( TableCellRenderer renderer, int row, int column) { Component c = super.prepareRenderer(renderer, row, column); if (!isRowSelected(row) ) { c.setBackground((hashMapcontainer .containsKey(row)) ? Color.GREEN : getBackground()); } return c; } @Override public boolean isCellEditable(int row, int column) { return false; } }; 

注意: hashMapcontainer是一个在源文件中全局范围的hashmap

现在这在某种程度上起作用,我将这个JTable添加到JFrameJTabbedPane 。 JTable在程序的整个运行时间内动态创建。 但是, prepareRenderer方法会导致所有创建的JTable中的所有特定单元格都被突出显示。

如何在所有JTable中保留单元格以保留自己特定的突出显示单元格,而不是让所有JTable中的单元格具有相同的突出显示单元格?

提前致谢!

渲染器是“橡皮图章”。 这基本上意味着他们将先前的设置带到下一个单元格。

您需要做的是提供“默认”行为

 if (!isRowSelected(row) ) { c.setBackground((hashMapcontainer .containsKey(row)) ? Color.GREEN : getBackground()); } else { // Define the default background color // Don't forget to take into the selection state } 

虽然我个人认为prepareRenderer在这种情况下可能是一个公平的解决方案,但你真的应该探索提供基线渲染器的可能性。 这是很多工作要做到正确,但具有可移植的优势(如果你更改表实现)以及允许其他人有机会定义给定单元格的高亮规则,你基本上已经消失并被覆盖, 恕我直言。

我还建议看看JXTable,因为它具有内置突出显示function

通常,基本Swing类的重写方法是个坏主意。 建议的方法是创建一个实现TableCellRendererJcomponent ,并使用setDefaultRenderer()将其应用于表。 请注意,默认情况下,JTable为Object,Number和Boolean类型提供其中的3个。 通常,渲染器看起来像这样:

 public class MyRenderer extends JLable, implements TableCellRenderer{ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { // Set up default state here c.setBackground(Color.white); c.setForeground(Color.black); // ... if (!isRowSelected(row) ) { c.setBackground((hashMapcontainer .containsKey(row)) ? Color.GREEN : getBackground()); } return c; } 

这为您提供了一个可重用的组件,而不是需要在创建它的每个位置扩展JTable。 至于在所有表中选择相同的单元格,这是由于isRowSelectedhashMapContainer访问全局状态而不是每个实例状态。 所有JComponent都有getClientPropertyputClientProperty 。 这些允许您将自己的状态对象附加到JTable 。 然后你的isRowSelected变成isRowSelected(table, row) ,它只是调用:

 MyObject myObj = (MyObject)table.getClientProperty("MySelectionProperty"); myObj.isRowSelected(row); 

同样可以从表中检索hashMapContainer

 MyHashContainer myHash = (MyHash)table.getClientProperty("MyHashContainer"); 

更新:

对于动态生成的表,这几乎是相同的。 表创建将如下所示:

 JTable t = new JTable(); // other typical table setup, t.setModel(...); etc t.setDefaultRenderer(String.class, myRenderer); t.putClientProperty("MySelectionProperty", new MyObject()); t.putClientProperty("MyHashContainer", new MyHashContainer()); 

值得注意的是,只要渲染器没有状态,就不需要为每个表创建一个实例。 我通常会创建一个并将其用于我的所有表格。

这是上面渲染器的更新,它不使用全局状态,而是查看表的属性:

 public class MyRenderer extends JLable, implements TableCellRenderer{ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { // Pull hashMapContainer from the per-table client properties MyHashContainer hashMapcontainer = (MyHashContainer)table.getClientProperty("MyHashContainer"); // Set defaults as above if (!isRowSelected(table, row) ) { // Same as above } return c; } // Private method to check for row selection private boolean isRowSelected(JTable t, int row) { int[] selectedRows = table.getSelectedRows(); for (int i = 0; i < selectedRows.length; i++) { if (selectedRows[i] == row) { return true; } } return false; } }