java “突出显示” JTable 中的特定行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11872003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Highlighting" specific rows in a JTable
提问by David
I would like to highlight specific rows in a JTable whenever the contents of the a cell match with an input from the user. The following code is what I have that works thus far:
每当单元格的内容与用户的输入匹配时,我想突出显示 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;
}
};
Notes: hashMapcontainer
is a hashmap
that is globally scoped within the source file.
注意:hashMapcontainer
是hashmap
在源文件中全局作用域的。
Now this works to some extent however, I am adding this JTable
to a JTabbedPane
that is within a JFrame
. JTables are dynamically created throughout the runtime of the program. However, the prepareRenderer
method causes all the specific cells in all the created JTables to be highlighted.
现在这个工作在一定程度上不过,我加入这JTable
一个JTabbedPane
是内部的JFrame
。JTable 是在程序运行时动态创建的。但是,该prepareRenderer
方法会导致所有创建的 JTable 中的所有特定单元格都突出显示。
How can I keep cells in all the JTables to keep their own specific highlighted cells rather than having all the JTables with the same exact highlighted cells in each?
如何在所有 JTables 中保留单元格以保留它们自己特定的突出显示单元格,而不是让所有 JTables 在每个单元格中都具有完全相同的突出显示单元格?
Thanks in advance!
提前致谢!
回答by MadProgrammer
The renderers are "rubber stamps". That basically means that they carry there previous settings over to the next cell.
渲染器是“橡皮图章”。这基本上意味着他们将先前的设置转移到下一个单元格。
What you need to do is provide a "default" behavior
您需要做的是提供“默认”行为
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
}
While I personally think that prepareRenderer
in this case is probably a fair solution, you really should explore the possibly of providing a base line renderer. This is a lot of work to get right but has the advantage of been portable (if you change table implementations) as well as allowing other
people the chance to define the highlight rules of a given cell, which you've basically just gone and overridden, IMHO.
虽然我个人认为prepareRenderer
在这种情况下可能是一个公平的解决方案,但您确实应该探索提供基线渲染器的可能性。这是很多工作要做,但具有可移植的优点(如果您更改表实现),并允许其他人有机会定义给定单元格的突出显示规则,您基本上刚刚删除并覆盖了这些规则, 恕我直言。
I'd also suggest taking a look at JXTableas it has in built highlighting
回答by Devon_C_Miller
Generally, overriding methods on the basic Swing classes is a bad idea. The recommended approach is to create a Jcomponent
that implements TableCellRenderer
and apply it to the table with setDefaultRenderer()
. Note that by default JTable supplies 3 of these for Object, Number, and Boolean types. Typically, a renderer looks something like this:
通常,覆盖基本 Swing 类的方法是一个坏主意。建议的方法是创建一个Jcomponent
实现TableCellRenderer
并将其应用到与表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;
}
This gives you a reusable component, rather than needing to extend JTable every place you create it. As for the same cells selecting in all tables, that is due to isRowSelected
and hashMapContainer
accessing global state instead of per-instance state. All JComponent
s have getClientProperty
and putClientProperty
. These allow you to attach your own state object to a JTable
. Then your isRowSelected
becomes isRowSelected(table, row)
, which simply calls:
这为您提供了一个可重用的组件,而不需要在您创建它的每个地方都扩展 JTable。对于在所有表中选择的相同单元格,这是由于isRowSelected
并hashMapContainer
访问全局状态而不是每个实例状态。所有JComponent
s 都有 getClientProperty
和putClientProperty
。这些允许您将自己的状态对象附加到JTable
. 然后你的isRowSelected
变成isRowSelected(table, row)
,它只是调用:
MyObject myObj = (MyObject)table.getClientProperty("MySelectionProperty");
myObj.isRowSelected(row);
Like wise the hashMapContainer
can also be retrieved from the table:
像明智的hashMapContainer
,也可以从表中检索:
MyHashContainer myHash = (MyHash)table.getClientProperty("MyHashContainer");
Update:
更新:
This is pretty much the same for a dynamically generated table. Table creation will look something like this:
这与动态生成的表几乎相同。表创建将如下所示:
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());
It's worth noting that as long as the renderer carries no state there is no need to create an instance per table. I'll usually create one and use it for all my tables.
值得注意的是,只要渲染器没有状态,就不需要为每个表创建一个实例。我通常会创建一个并将其用于我的所有表。
Here's an update to the renderer above that does not use global state, rather looks to the table for properties:
这是上面渲染器的更新,它不使用全局状态,而是查看属性表:
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;
}
}