แก้ไขข้อผิดพลาดพื้นหลังสีของ JTextPane เมื่อใช้ Nimbus หรือ GTK LookAndFeeel โดยการแทนที่วิธีการ

ฉันพยายามเปลี่ยนสีพื้นหลังของ JTextPane ซึ่งมีเหมือน Cell ของ 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);

ฉันต้องการ Color ดั้งเดิมของ Nimbus และสีสำหรับ Select Background of Cell of 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 (ไม่ได้ใช้ในคลาสก่อนหน้า เพียงเพื่อแสดงผลที่ตามมาของ 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);
    }
  }

ฉันกำลังพยายามตรวจสอบมรดกของ 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 แหล่งที่มา