首页 > 解决方案 > JTable/setDefaultRenderer 多选行

问题描述

我已经在整个互联网上进行了字面搜索,但找不到解决我问题的有效解决方案。

我有一个JTable,我想动态更改多行的背景颜色,而不影响其他行的背景颜色,这些颜色可能已经被更改。

颜色变化由actionListeneraJMenuItem的 a触发ContextMenu,如下图所示:

在此处输入图像描述

到目前为止我尝试的代码如下:

    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();
      // });
    }

如果有人有有效的解决方案,请分享它,将不胜感激!

编辑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;
          }
        });
      });
    }

如您所见,有些东西不在那里...

编辑 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% 解决,谢谢大家!

标签: javaswingjtablebackground-color

解决方案


您可以保留将行索引映射到颜色的映射,并在默认渲染器中使用它。在动作监听器中,您只需将具有指定颜色的行索引放入此地图中。

final Map<Integer, Color> highlightedRows = new HashMap<>();
highlightedRows.put(1, Color.GREEN);
highlightedRows.put(2, Color.YELLOW);
    
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
        
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        final var cmp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        final var color = highlightedRows.get(row);
        if (color != null && !isSelected) {
            cmp.setBackground(color);
        }
        return cmp;
    }
});

结果

在此处输入图像描述

编辑:完全工作的例子

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

public class TableRowHighlightExample {

    private final Map<Integer, Color> highlightedRows = new HashMap<>();

    private JTable table;

    private JPopupMenu createHighlightMenu() {
        final JPopupMenu highlightMenu = new JPopupMenu();

        final Color[] colors = { 
                Color.RED, 
                Color.ORANGE, 
                Color.YELLOW, 
                Color.GREEN, 
                Color.BLUE, 
                Color.MAGENTA,
                Color.PINK, 
                Color.GRAY 
        };
                
        // Add null
        for (final Color color : colors) {
            final JMenuItem x = new JMenuItem();
            x.setOpaque(true);
            x.setBackground(color);

            highlightMenu.add(x);

            x.addActionListener(e -> {
                final int[] selectedRows = this.table.getSelectedRows();
                for (final int row : selectedRows) {
                    highlightedRows.put(row, color);
                }
            });
        }
        
        return highlightMenu;
    }

    private JTable createTable() {
        final String[] colNames = { "Column 0" };
        final Object[][] data = { { "Row 0" }, { "Row 1" }, { "Row 2" }, { "Row 3" } };

        final var table = new JTable(data, colNames);
        table.setPreferredSize(new Dimension(500, 200));
        table.setComponentPopupMenu(this.createHighlightMenu());
        
        table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {

            @Override
            public Component getTableCellRendererComponent(
                    JTable table, Object value, boolean isSelected,
                    boolean hasFocus, int row, int column) {
                
                final var cmp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                cmp.setBackground(highlightedRows.get(row));
                return cmp;
            }
        });
        
        return table;
    }

    public void run() {
        final var frame = new JFrame();
        this.table = this.createTable();
        
        frame.add(new JScrollPane(this.table));
        frame.setSize(500, 200);        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);     
    }
    
    public static void main(String[] args) {
        new TableRowHighlightExample().run();
    }
}

在此处输入图像描述


推荐阅读