【发布时间】:2021-12-21 04:42:16
【问题描述】:
我在整个 Internet 上进行了逐字搜索,但找不到解决问题的有效方法。
我有一个JTable,我想动态更改多行的背景颜色,而不影响可能已经更改的其他行的背景颜色。
颜色变化由JMenuItem 的ContextMenu 上的actionListener 触发,如下所示:
目前我尝试的代码如下:
JMenu highlightMenu = new JMenu("Highlight");
// Add null
for (Color color : Arrays.asList(Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA,
Color.PINK, Color.GRAY)) {
JMenuItem x = new JMenuItem();
x.setOpaque(true);
x.setBackground(color);
highlightMenu.add(x);
x.addHierarchyListener(e -> x.setText(tab.getTable()
.getValueAt(tab.getTable().getSelectedRow(), tab.getTable().getColumn("Server").getModelIndex()).toString()));
x.addActionListener(e -> IntStream.of(tab.getTable().getSelectedRows())
.forEach(row -> ((Component) tab.getTable().getModel().getValueAt(row, 0)).setBackground(color)));
// x.addActionListener(e -> {
// IntStream.of(tab.getTable().getSelectedRows())
// .forEach(r -> tab.getTable().setDefaultRenderer(Object.class, new
// DefaultTableCellRenderer() {
// @Override
// public Component getTableCellRendererComponent(JTable table, Object value,
// boolean isSelected,
// boolean hasFocus, int row, int column) {
// Component comp = super.getTableCellRendererComponent(table, value,
// isSelected, hasFocus, row, column);
// if (r == row) {
// comp.setBackground(color);
// } else {
// comp.setBackground(null);
// }
// return comp;
// }
// }));
// tab.getTable().repaint();
// });
}
如果有人有可行的解决方案,请分享,将不胜感激! ????
EDIT 0:我清理了编辑,因为它们太多了,所以我添加了调试字符串,这个表根本没有表现出来,请看下面的截图:
注意:也不确定为什么,但似乎该表被迭代多次 (5),如上面的输出所示,这不应该是这种情况,因为每个 JMenuItem 都有自己的事件侦听器......而且它应该只触发一次,具体取决于选择的颜色/JMenuItem...
以及结果表:
来自以下代码:
for (Color color : Arrays.asList(Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA,
Color.PINK, Color.GRAY)) {
JMenuItem x = new JMenuItem();
x.setOpaque(true);
x.setBackground(color);
x.setForeground(Color.BLACK);
highlightMenu.add(x);
x.addHierarchyListener(e -> x.setText(tab.getTable()
.getValueAt(tab.getTable().getSelectedRow(), tab.getTable().getColumn("Server").getModelIndex()).toString()));
x.addActionListener(e -> {
IntStream.of(tab.getTable().getSelectedRows()).forEach(row -> this.highlightedRows.put(row, color)
// this.highlightedRows.put(row, Arrays.asList(Color.BLACK, color)
);
tab.getTable().setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
stdOut.println(String.format("%s -> %s", row, highlightedRows.get(row)));
if (highlightedRows.get(row) != null) {
stdOut.println("XXXXXXX");
component.setBackground(highlightedRows.get(row));
}
// if (!isSelected && highlightedRows.containsKey(row)) {
// component.setForeground(highlightedRows.get(row).get(0));
// component.setBackground(highlightedRows.get(row).get(1));
// }
return component;
}
});
});
}
如你所见,有些地方不对劲……
EDIT N:用以下代码几乎解决了这个问题:
for (Color color : Arrays.asList(Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA,
Color.PINK, Color.GRAY)) {
final JMenuItem x = new JMenuItem();
x.setOpaque(true);
x.setBackground(color);
x.setForeground(Color.BLACK);
highlightMenu.add(x);
x.addHierarchyListener(e -> x.setText(tab.getTable()
.getValueAt(tab.getTable().getSelectedRow(), tab.getTable().getColumn("Server").getModelIndex()).toString()));
x.addActionListener(e -> {
IntStream.of(tab.getTable().getSelectedRows())
.forEach(row -> this.highlightedRows.put(row, Arrays.asList(Color.BLACK, color)));
// row -> this.highlightedRows.put(row, color)
tab.getTable().setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
final Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
column);
stdOut.println(String.format("%s -> %s", row, highlightedRows.get(row)));
if (highlightedRows.containsKey(row)) {
component.setForeground(highlightedRows.get(row).get(0));
component.setBackground(highlightedRows.get(row).get(1));
} else {
if (row % 2 == 0) {
component.setBackground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.background"));
} else {
component
.setBackground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.alternateRowColor"));
}
component.setForeground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.foreground"));
}
if (isSelected) {
component
.setForeground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.selectionForeground"));
component
.setBackground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.selectionBackground"));
}
return component;
}
});
});
}
现在唯一的事情是事件侦听器被多次调用,请参阅以前的编辑,虽然这个问题已经解决,但是这将 100% 解决,谢谢大家! ????
【问题讨论】:
-
行颜色必须是拖曳中每个单元格的属性,因此可以由渲染器提取
-
@MadProgrammer 你能提供一个代码 sn-p/example 来说明如何实现这一点吗?
-
您需要在所有单元格上设置表格单元格渲染器。你不能只改变背景颜色。
-
您的渲染器不完整。例如,您会丢失表格的默认设置,因为您总是假设每一行都有自定义背景。只有在地图中找到 Color 实例或未选择行时,才应重置背景。此外,您的渲染器仅适用于具有“字符串”值的列。包含其他数据的列不受影响。看; Table Row Rendering 用于将突出显示应用于所有列的方法。
-
我查看了表格行渲染,但我认为它不适用 - 如果您希望突出显示所有列。目前您的第一列未突出显示。使用地图的概念也需要像您在此处那样实现。
标签: java swing jtable background-color