Исправление ошибки фона Цвет JTextPane при использовании Nimbus или GTK LookAndFeel путем переопределения методов

Я пытался изменить цвет фона JTextPane, содержащийся как ячейка JTable, с проблемами, связанными с этим вопросом JTable, обновить ячейку цветов, когда LookAndFeel Nimbus или GTK используются

Позже я обнаружил ошибку (и не применимое для меня решение) https://bugs.openjdk.java.net/browse/JDK-8058704?jql=order%20by%20lastViewed%20DESC

UIManager.put("TextPane[Enabled].backgroundPainter", new Painter<JComponent>() {
    @Override
    public void paint(Graphics2D g, JComponent comp, int width, int height) {
        g.setColor(comp.getBackground());
        g.fillRect(0, 0, width, height);
    }
});

И этот ответ https://stackoverflow.com/a/22674770/1410223

JEditorPane area = new JEditorPane();

  Color bgColor = Color.BLACK;
  UIDefaults defaults = new UIDefaults();
  defaults.put("EditorPane[Enabled].backgroundPainter", bgColor);
  area.putClientProperty("Nimbus.Overrides", defaults);
  area.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
  area.setBackground(bgColor);

Мне также нужен исходный цвет Nimbus и цвет для выбора фона ячейки JTable ...

Здесь полный и функциональный код (исправление импорта библиотек).

public class JTextPaneSynthTest extends JFrame {

  public JTextPaneSynthTest() {

    JTextPane textPane = new JTextPane();
    textPane.setText("something");


    MetalLookAndFeel metalLAF = new MetalLookAndFeel(); //BasicTextPaneUI
    MotifLookAndFeel motifLAF = new MotifLookAndFeel(); //MotifTextPaneUI
    NimbusLookAndFeel nimbusLAF = new NimbusLookAndFeel(); //NimbusLookAndFeel extends SynthLookAndFeel
    SynthLookAndFeel synthLAF = new SynthLookAndFeel(); //SynthTextPaneUI // SynthLookAndFeel extends BasicLookAndFeel

    BasicTextPaneUI basicTextPaneUI = new BasicTextPaneUI(); // BasicTextPaneUI extends BasicEditorPaneUI
    MotifTextPaneUI motifTextPaneUI = new MotifTextPaneUI(); // MotifTextPaneUI extends BasicTextPaneUI
    SynthTextPaneUI synthTextPaneUI = new SynthTextPaneUI(); // SynthTextPaneUI extends SynthEditorPaneUI (SynthEditorPaneUI extends BasicEditorPaneUI implements SynthUI)

    String laf = UIManager.getLookAndFeel().getName();
    System.out.println("laf:" + laf);
    if (laf.contains("Nimbus") || laf.contains("GTK+")) {
      textPane.setUI(getSynthTextPaneUI());
      textPane.revalidate();
    }
    TextUI textUI = textPane.getUI();
    System.out.println("textUI.getClass():" + textUI.getClass());

    JButton button = new JButton("Change Color");
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        textPane.setBackground(Color.green);
        textPane.setForeground(Color.red);
        textPane.repaint();
      }
    });

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

  private static SynthTextPaneUI getSynthTextPaneUI() {
    return new SynthTextPaneUI() {

      @Override
      public void installUI(JComponent c) {
        super.installUI(c);
        updateBackground(c.getBackground());
        updateForeground(c.getForeground());
        updateFont(c.getFont());
      }

      private void updateBackground(Color color) {
        StyledDocument doc = (StyledDocument) getComponent().getDocument();
        //doc.setCharacterAttributes(0, doc.getLength(), s, true);
        Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);

        if (style == null) {
          return;
        }

        if (color == null) {
          style.removeAttribute(StyleConstants.Background);
        } else {
          StyleConstants.setBackground(style, color);
        }
      }

      private void updateForeground(Color color) {
        StyledDocument doc = (StyledDocument) getComponent().getDocument();
        Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);

        if (style == null) {
          return;
        }

        if (color == null) {
          style.removeAttribute(StyleConstants.Foreground);
        } else {
          StyleConstants.setForeground(style, color);
        }
      }

      private void updateFont(Font font) {
        StyledDocument doc = (StyledDocument) getComponent().getDocument();
        Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);

        if (style == null) {
          return;
        }

        if (font == null) {
          style.removeAttribute(StyleConstants.FontFamily);
          style.removeAttribute(StyleConstants.FontSize);
          style.removeAttribute(StyleConstants.Bold);
          style.removeAttribute(StyleConstants.Italic);
        } else {
          StyleConstants.setFontFamily(style, font.getName());
          StyleConstants.setFontSize(style, font.getSize());
          StyleConstants.setBold(style, font.isBold());
          StyleConstants.setItalic(style, font.isItalic());
        }
      }
    };

  }
}

Код для изменения цвета ячеек JTable (Он не используется в предыдущем классе, только для демонстрации последствий ошибки)

  private class CellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {

    private final Panel panel = new Panel();  // This class contains a JTextPane, named textPane

    //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");
          }
        }
        // In order to fix the problem with GTK LookAndFeel
        background = new Color(background.getRed(), background.getGreen(), background.getBlue());
        foreground = new Color(foreground.getRed(), foreground.getGreen(), foreground.getBlue());

        panel.getTextPane().setBackground(background);
        panel.getTextPane().setForeground(foreground);

        return panel;
      }

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

Я пытался просмотреть наследие LookAndFeel, чтобы найти множество решений, но не смог.

//http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java
//AquaLookAndFeel aquaLAF = new AquaLookAndFeel(); //AquaTextPaneUI // AquaLookAndFeel extends BasicLookAndFeel
//http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/macosx/classes/com/apple/laf/AquaTextPaneUI.java
//AquaTextPaneUI aquaTextPaneUI = new AquaTextPaneUI(); // AquaTextPaneUI extends BasicTextPaneUI

//http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java
//GTKLookAndFeel gtkLAF = new GTKLookAndFeel(); //SynthTextPaneUI // GTKLookAndFeel extends SynthLookAndFeel

//http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java
//WindowsLookAndFeel windowsLAF = new WindowsLookAndFeel(); //WindowsTextPaneUI // WindowsLookAndFeel extends BasicLookAndFeel
//http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java
//WindowsTextPaneUI windowsTextPaneUI = new WindowsTextPaneUI(); //WindowsTextPaneUI extends BasicTextPaneUI (BasicTextPaneUI extends BasicEditorPaneUI)

Какие методы вы предлагаете переопределить (изменить цвет фона JTextPane при использовании Nimbus), чтобы решить эту проблему путем изменения кода LookAndFeels?


person Anita    schedule 30.10.2019    source источник