JTable, обновите ячейку Colors, когда используются LookAndFeel Nimbus или GTK - PullRequest
1 голос
/ 25 октября 2019

У меня есть резюме кодов и ответов ...

Я пытаюсь перекрасить JPanel (что содержит другие объекты), содержащиеся в JTable ячейках.

Чтобы следовать этим ответам https://stackoverflow.com/a/28368503/1410223

ПОЛНЫЙ КОД ИСТОЧНИКА

public class JTableSynthTest extends JFrame {

  String[] hdrsObjects = new String[]{
    "Name", "Last Name", "Sport", " Level"
  };

  Object[][] matrixInfo = {
    {new Info("Kathy"), new Info("Smith"), new Info("Snowboarding"), new Info("1")},
    {new Info("John"), new Info("Doe"), new Info("Rowing"), new Info("0")},
    {new Info("Sue"), new Info("Black"), new Info("Knitting"), new Info("3")},
    {new Info("Jane"), new Info("White"), new Info("Speed reading"), new Info("0")},
    {new Info("Joe"), new Info("Brown"), new Info("Pool"), new Info("2")}
  };

  Object[][] objectMatrix = {
    {"Kathy", "Smith", "Snowboarding", "1"},
    {"John", "Doe", "Rowing", "0"},
    {"Sue", "Black", "Knitting", "3"},
    {"Jane", "White", "Speed reading", "0"},
    {"Joe", "Brown", "Pool", "2"}
  };

  public JTableSynthTest() {
    List<Point> listSelectedCell = new ArrayList<>();

    //JTable table = new JTable(new DefaultTableModel(objectMatrix, hdrsObjects)) {
    JTable table = new JTable(new TableModel(matrixInfo, hdrsObjects)) {

      @Override
      public void updateUI() {
        super.updateUI();
        setIntercellSpacing(new Dimension(1 /*gapWidth*/, 2/*gapHeight*/));
        setGridColor(Color.DARK_GRAY);
        setShowHorizontalLines(true);
        setShowVerticalLines(true);
        getTableHeader().setUI(null);
        CellRenderer myCellRenderer = new CellRenderer();
        CellEditor myCellEditor = new CellEditor();
        //setDefaultRenderer(Object.class, myCellRenderer);

        for (int idx = 0; idx < getColumnModel().getColumnCount(); idx++) {
          TableColumn tc = getColumnModel().getColumn(idx);
          myCellRenderer.setHorizontalAlignment(SwingConstants.CENTER);
          tc.setCellRenderer(myCellRenderer);
          tc.setCellEditor(myCellEditor);
          tc.setPreferredWidth(new Panel().getWidth());
        }
        setRowHeight(10 + getRowHeight() + getIntercellSpacing().height);
      }

      @Override
      public boolean isCellSelected(int row, int column) {
        return listSelectedCell.contains(new Point(row, column));
      }
    };

    JButton button = new JButton("Selected Cells");
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        listSelectedCell.clear();
        int rows = table.getRowCount();
        int cols = table.getColumnCount();
        int row = new Random().nextInt(rows);
        int col = new Random().nextInt(cols);
        Point point = new Point(row, col);
        if (!listSelectedCell.contains(point)) {
          listSelectedCell.add(point);
        }
        //((TableModel) table.getModel()).fireTableDataChanged();
        //((DefaultTableModel) table.getModel()).fireTableDataChanged();
        table.repaint();
      }
    });

    JScrollPane pane = new JScrollPane(table);

    JPanel lower = new JPanel();
    lower.setLayout(new BoxLayout(lower, BoxLayout.X_AXIS));
    lower.add(button);
    //lower.add(textPane);

    JPanel main = new JPanel();
    main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
    main.add(pane);
    main.add(lower);
    this.add(main);

    this.setSize(800, 600);
    this.setVisible(true);

  }

  public static void main(String[] args) {

    try {
      /*
      javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
      javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
      javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");

      javax.swing.UIManager.setLookAndFeel("com.apple.laf.AquaLookAndFeel");
      javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
      javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
      javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel");
       */
      javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");

    } catch (Exception ex) {
      ex.printStackTrace();
    }

    new JTableSynthTest();
  }

  private class Panel extends JPanel {

    private final JTextPane textPane = new JTextPane();

    public Panel() {
      add(textPane, BorderLayout.NORTH);
      int minWidth = (new JTextPane()).getMinimumSize().width;
      int minHeight = (new JTextPane()).getMinimumSize().height;
      textPane.setMinimumSize(new Dimension(minWidth, minHeight));
      Dimension d = getMinimumSize();
      setSize(d);
      setPreferredSize(d);
      setMaximumSize(d);
    }

    public Panel(Info info) {
      this();
      setData(info);
    }

    public JTextPane getTextPane() {
      return textPane;
    }

    public Info getData() {
      return new Info(textPane.getText()
      );
    }

    public void setData(Info info) {
      textPane.setText(info.getData());
    }

    public void setSelected(boolean isSelected, JTable table, int row) {
      /*
      if (isSelected) {
        this.setBackground(table.getSelectionBackground());
      } else {
        this.setBackground(table.getBackground());
      }
      String laf = UIManager.getLookAndFeel().getName().toLowerCase();
      if (laf.contains("nimbus")) {
        NimbusLookAndFeel nimbusLAF = new NimbusLookAndFeel();
        if (isSelected) {
          this.getTextPane().setBackground(nimbusLAF.getDerivedColor("Table[Enabled+Selected].textBackground", 0.0f, 0.0f, 0.0f, 0, false));
          this.getTextPane().setForeground(nimbusLAF.getDerivedColor("Table[Enabled+Selected].textForeground", 0.0f, 0.0f, 0.0f, 0, false));
        } else {
          if (row % 2 == 0) {
            this.getTextPane().setBackground(nimbusLAF.getDerivedColor("Table.background", 0.0f, 0.0f, 0.0f, 0, false));
          } else {
            this.getTextPane().setBackground(nimbusLAF.getDerivedColor("Table.alternateRowColor", 0.0f, 0.0f, 0.0f, 0, false));
          }
          this.getTextPane().setForeground(nimbusLAF.getDerivedColor("Table.foreground", 0.0f, 0.0f, 0.0f, 0, false));
        }
      }
      */
    }
  }

  private class Info {

    private String data;

    public Info(String data) {
      this.data = data;
    }

    public String getData() {
      return data;
    }

    public void setData(String data) {
      this.data = data;
    }
  }

  private class CellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {

    private final Panel panel = new Panel();

    //javax.swing.table.TableCellRenderer
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

      if (value instanceof Info) {
        panel.setData((Info) value);

        String laf = UIManager.getLookAndFeel().getName().toLowerCase();
        Color background;
        Color foreground;
        if (laf.contains("nimbus")) {
          NimbusLookAndFeel nimbusLAF = new NimbusLookAndFeel();
          if (isSelected) {
            background = (nimbusLAF.getDerivedColor("nimbusSelectionBackground", 0.0f, 0.0f, 0.0f, 0, false));
            foreground = (nimbusLAF.getDerivedColor("nimbusLightBackground", 0.0f, 0.0f, 0.0f, 0, false));
          } else {
            if (row % 2 == 0) {
              background = nimbusLAF.getDerivedColor("Table.background", 0.0f, 0.0f, 0.0f, 0, false);
            } else {
              background = nimbusLAF.getDerivedColor("Table.alternateRowColor", 0.0f, 0.0f, 0.0f, 0, false);
            }
            foreground = nimbusLAF.getDerivedColor("Table.foreground", 0.0f, 0.0f, 0.0f, 0, false);
          }
        } else {
          if (isSelected) {
            background = (Color) UIManager.get("Table.selectionBackground");
            foreground = (Color) UIManager.get("Table.selectionForeground");
          } else {
            background = (Color) UIManager.get("Table.background");
            foreground = (Color) UIManager.get("Table.foreground");
          }
        }
        background = new Color(background.getRed(), background.getGreen(), background.getBlue());
        foreground = new Color(foreground.getRed(), foreground.getGreen(), foreground.getBlue());

        System.out.println("background:" + background);
        System.out.println("foreground:" + foreground);

        panel.getTextPane().setBackground(background/*Color.CYAN*/);
        panel.getTextPane().setForeground(foreground/*Color.PINK*/);

        return panel;
      }

      return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    }
  }

  private class CellEditor extends AbstractCellEditor implements TableCellEditor {

    protected Object output;
    private final Panel panel = new Panel();

    @Override //javax.swing.CellEditor
    public Object getCellEditorValue() {
      //Returns the value contained in the editor.
      if (output instanceof Panel) {
        return panel.getData();
      }
      return null;
    }

    @Override //javax.swing.table.TableCellEditor
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
      //Sets an initial value for the editor.
      if (value instanceof Info) {
        panel.setData((Info) value);
        panel.setSelected(true, table, row);
        output = panel;
        return panel;
      }
      return null;
    }
  }

  private class TableModel extends AbstractTableModel {

    private Object[][] data;
    private Object[] columns;

    public TableModel(Object[][] data, Object[] columns) {
      this.data = data;
      this.columns = columns;
    }

    //javax.swing.table.TableModel
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
      if (data != null) {
        if (data.length > 0) {
          return data[rowIndex][columnIndex];
        }
      }
      return null;
    }

    //javax.swing.table.TableModel
    @Override
    public int getColumnCount() {
      return ((columns == null) ? 0 : columns.length);
    }

    //javax.swing.table.TableModel
    @Override
    public int getRowCount() {
      return ((data == null) ? 0 : data.length);
    }

    //javax.swing.table.AbstractTableModel
    @Override
    public Class getColumnClass(int columnIndex) {
      if (data != null) {
        if (data.length > 0) {
          if (data[0][columnIndex] instanceof Panel) {
            return Panel.class;
          }
          return Object.class;
        }
      }
      return Object.class;
    }

    //javax.swing.table.AbstractTableModel
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      if (data != null) {
        if (data.length > 0) {
          if (data[0][columnIndex] instanceof Panel) {
            return true;
          }
          return true;
        }
      }
      return false;
    }

    //javax.swing.table.AbstractTableModel
    @Override
    public void setValueAt(Object value, int row, int col) {
      data[row][col] = value;
      fireTableCellUpdated(row, col);
    }

    //javax.swing.table.AbstractTableModel
    @Override
    public String getColumnName(int columnIndex) {
      return (String) columns[columnIndex];
    }

  }
}

Мой код работает для Look And Feels:

  • com.apple.laf.AquaLookAndFeel
  • javax.swing.plaf.metal.MetalLookAndFeel
  • com.sun.java.swing.plaf.motif.MotifLookAndFeel
  • com.sun.java.swing.plaf.windows.WindowsLookAndFeel
  • com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel

Но не удается

  • javax.swing.plaf.nimbus.NimbusLookAndFeel // РАБОТА НЕ БУДЕТ ПРЕДОСТАВЛЯТЬСЯ!
  • com.sun.java.swing.plaf.gtk.GTKLookAndFeel // РАБОТАЕТ НЕ РАБОТАЕТ!

Даже с этим Примером , меняющим свой метод main.

  public static void main(String[] args) {
    try {
      UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
    } catch (Exception ex) {
      Logger.getLogger(JTableTest.class.getName()).log(Level.SEVERE, null, ex);
    }
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new JTableTest());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
    });
  }

ПРИМЕЧАНИЕ:

http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java

GTKLookAndFeel extends SynthLookAndFeel

http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java

NimbusLookAndFeel extends SynthLookAndFeel

Как исправить это поведение (НЕ перекрашивать, когда JTable выбранных / невыбранных ячеек, когда Nimbus, Gtk Look And Feels)?

...