Fixing Background bug Color of JTextPane when Nimbus or GTK LookAndFeeel is Used, by overriding methods

这一生的挚爱 提交于 2019-12-11 10:57:42

问题


I was trying to change background Color of JTextPane, contained like a Cell of JTable with problems related in this question JTable, update Colors Cell when LookAndFeel Nimbus or GTK are used

I discovered later the bug (and not for me applicable solution) 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);
    }
});

And this answer 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);

I need too the original Color of Nimbus and, the color for Select Background of Cell of JTable ...

Here complete and functional code (Fixing imports libraries).

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

  }
}

The code for JTable Cells Color changing (It is not used in the before class, only to show the consequences of the Bug)

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

I was trying to review, the heritance of LookAndFeel's in order to discover a plenty solution, but I could not.

//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)

What methods do you suggest to override (to change Background Color of JTextPane when Nimbus is used), in order to solve it by changing the LookAndFeels code?

来源:https://stackoverflow.com/questions/58618209/fixing-background-bug-color-of-jtextpane-when-nimbus-or-gtk-lookandfeeel-is-used

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!