正确的方式使用JTextPane创建Class,JTree,DefaultTreeCellRenderer

时间:2018-08-19 01:19:39

标签: java swing jtree jtextpane nimbus

我有这个课程是为了使用JTree在一片叶子中显示多种颜色...

班级为TextPaneDefaultTreeCellRenderer

import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.tree.*;

public class TextPaneDefaultTreeCellRenderer extends DefaultTreeCellRenderer {

  TextPaneTreeCellRenderer textPaneScrollPane = new TextPaneTreeCellRenderer();

  public TextPaneDefaultTreeCellRenderer() {
    initialize();
  }

  private void initialize() {
    textPaneScrollPane.setBackgroundNonSelectionColor(getBackgroundNonSelectionColor());
    textPaneScrollPane.setBackgroundSelectionColor(getBackgroundSelectionColor());
    textPaneScrollPane.setTextNonSelectionColor(getTextNonSelectionColor());
    textPaneScrollPane.setTextSelectionColor(getTextSelectionColor());
  }

  @Override
  public Component getTreeCellRendererComponent(JTree tree,
      Object value, boolean selected, boolean expanded, boolean leaf,
      int row, boolean hasFocus) {
    if (leaf) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
      Object obj = node.getUserObject();
      if (obj != null) {
        if (obj instanceof DecoratedText || obj instanceof DecoratedText[]) {
          if (textPaneScrollPane == null) {
            System.out.println("textPaneScrollPane:" + textPaneScrollPane);
          }
          return textPaneScrollPane.getTreeCellRendererComponent(tree, value,
              selected, expanded, leaf, row, hasFocus);
        }
      }
    }
    return super.getTreeCellRendererComponent(tree, value, selected,
        expanded, leaf, row, hasFocus);
  }
}

class TextPaneTreeCellRenderer extends DefaultTreeCellRenderer {

  JTextPane textPane;

  public TextPaneTreeCellRenderer() {
    textPane = new JTextPane();
    add(textPane);
  }

  @Override
  public void setBackgroundNonSelectionColor(Color color) {
    this.backgroundNonSelectionColor = color;
  }

  @Override
  public void setBackgroundSelectionColor(Color color) {
    this.backgroundSelectionColor = color;
  }

  @Override
  public void setTextNonSelectionColor(Color color) {
    this.textNonSelectionColor = color;
  }

  @Override
  public void setTextSelectionColor(Color color) {
    this.textSelectionColor = color;
  }

  @Override
  public Component getTreeCellRendererComponent(JTree tree,
      Object value, boolean selected, boolean expanded, boolean leaf,
      int row, boolean hasFocus) {

    DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
    Object object = node.getUserObject();

    if (selected) {
      setForeground(textSelectionColor);
      setBackground(backgroundSelectionColor);
      textPane.setForeground(textSelectionColor);
      textPane.setBackground(backgroundSelectionColor);
    } else {
      setForeground(textNonSelectionColor);
      setBackground(backgroundNonSelectionColor);
      textPane.setForeground(textNonSelectionColor);
      textPane.setBackground(backgroundNonSelectionColor);
    }

    textPane.setText("");
    Document doc = textPane.getStyledDocument();
    if (object != null && object instanceof DecoratedText) {
      DecoratedText decText = (DecoratedText) object;
      try {
        doc.insertString(doc.getLength(), decText.getText(), getAttributeSet(decText));
      } catch (BadLocationException ex) {
        Logger.getLogger(TextPaneTreeCellRenderer.class.getName()).log(Level.SEVERE, null, ex);
      }
    } else if (object != null && object instanceof DecoratedText[]) {
      DecoratedText[] arrayDecText = (DecoratedText[]) object;
      for (DecoratedText decText : arrayDecText) {
        try {
          //doc.insertString(doc.getLength(), decText.getText(), getAttributeSet(decText));
          doc.insertString(doc.getLength(), decText.getText(), decText.getAttributeSet(textPane));
        } catch (BadLocationException ex) {
          System.out.println("decText:" + decText);
          System.out.println("arrayDecText:" + arrayDecText);
          System.out.println("doc:" + doc.getLength());
          Logger.getLogger(TextPaneTreeCellRenderer.class.getName()).log(Level.SEVERE, null, ex);
        }
      }
    } else {
      return new DefaultTreeCellRenderer().getTreeCellRendererComponent(tree,
          value, leaf, expanded, leaf, row, hasFocus);
    }
    return textPane;
  }

  private SimpleAttributeSet getAttributeSet(DecoratedText decoratedText) {
    SimpleAttributeSet attrSet = new SimpleAttributeSet();
    if (decoratedText != null) {
      if (decoratedText.getBackground() != null) {
        StyleConstants.setBackground(attrSet, decoratedText.getBackground());
      } else {
        StyleConstants.setBackground(attrSet, textPane.getBackground());
      }
      if (decoratedText.getForeground() != null) {
        StyleConstants.setForeground(attrSet, decoratedText.getForeground());
      } else {
        StyleConstants.setForeground(attrSet, textPane.getForeground());
      }
      Font font;
      if (decoratedText.getFont() != null) {
        font = decoratedText.getFont();
      } else {
        font = textPane.getFont();
      }
      StyleConstants.setFontFamily(attrSet, font.getFamily());
      StyleConstants.setItalic(attrSet, font.isItalic());
      StyleConstants.setBold(attrSet, font.isBold());
      StyleConstants.setFontSize(attrSet, font.getSize());
    }
    return attrSet;
  }

}

enter image description here

替代类为TreeCellRendererTextPane

import java.awt.Component;
import java.util.logging.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.tree.*;

public class TreeCellRendererTextPane extends JTextPane implements TreeCellRenderer {

  @Override
  public Component getTreeCellRendererComponent(JTree tree,
      Object value, boolean selected, boolean expanded, boolean leaf,
      int row, boolean hasFocus) {
    if (leaf) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
      Object obj = node.getUserObject();
      if (obj != null) {
        if (obj instanceof DecoratedText || obj instanceof DecoratedText[]) {
          this.setText("");
          Document doc = this.getStyledDocument();
          if (obj instanceof DecoratedText) {
            DecoratedText decText = (DecoratedText) obj;
            try {
              doc.insertString(doc.getLength(), decText.getText(), decText.getAttributeSet(this));
            } catch (BadLocationException ex) {
              Logger.getLogger(TextPaneTreeCellRenderer.class.getName()).log(Level.SEVERE, null, ex);
            }
          }
          if (obj instanceof DecoratedText[]) {
            DecoratedText[] arrayDecText = (DecoratedText[]) obj;
            for (DecoratedText decText : arrayDecText) {
              try {
                doc.insertString(doc.getLength(), decText.getText(), decText.getAttributeSet(this));
              } catch (BadLocationException ex) {
                System.out.println("decText:" + decText);
                System.out.println("arrayDecText:" + arrayDecText);
                System.out.println("doc:" + doc.getLength());
                Logger.getLogger(TextPaneTreeCellRenderer.class.getName()).log(Level.SEVERE, null, ex);
              }
            }
          }
        } else {
          return new DefaultTreeCellRenderer().getTreeCellRendererComponent(tree,
              value, leaf, expanded, leaf, row, hasFocus);
        }
      }
    }
    return this;
  }
}

enter image description here

您会看到Root(未正确显示叶子,文件夹被省略,单词仅显示第一个字母)

我的另一堂课是DecoratedText

import java.awt.*;
import javax.swing.JTextPane;
import javax.swing.text.*;

public class DecoratedText {

  private String text;
  private Color background;// = new JLabel().getBackground();
  private Color foreground;// = new JLabel().getForeground();
  private Font font;// = new JLabel().getFont();

  public DecoratedText(String text) {
    this.text = text;
  }

  public DecoratedText(String text, Font font) {
    this.text = text;
    this.font = font;
  }

  public DecoratedText(String text, Color foreground) {
    this.text = text;
    this.foreground = foreground;
  }

  public DecoratedText(String text, Color foreground, Font font) {
    this.text = text;
    this.foreground = foreground;
    this.font = font;
  }

  public DecoratedText(Color background, String text) {
    this.background = background;
    this.text = text;
  }

  public DecoratedText(Color background, String text, Font font) {
    this.background = background;
    this.text = text;
    this.font = font;
  }

  public DecoratedText(Color background, String text, Color foreground) {
    this.background = background;
    this.text = text;
    this.foreground = foreground;
  }

  public DecoratedText(Color background, String text, Color foreground, Font font) {
    this.background = background;
    this.text = text;
    this.foreground = foreground;
    this.font = font;
  }

  public String getText() {
    return text;
  }

  public void setText(String text) {
    this.text = text;
  }

  public Color getBackground() {
    return background;
  }

  public void setBackground(Color background) {
    this.background = background;
  }

  public Color getForeground() {
    return foreground;
  }

  public void setForeground(Color foreground) {
    this.foreground = foreground;
  }

  public Font getFont() {
    return font;
  }

  public void setFont(Font font) {
    this.font = font;
  }

  @Override
  public String toString() {
    return "DecoratedText{" + "text=" + text + ", background=" + background
        + ", foreground=" + foreground + ", font=" + font + "}";
  }

  public SimpleAttributeSet getAttributeSet(JTextPane textPane) {
    SimpleAttributeSet attrSet = new SimpleAttributeSet();
    if (getBackground() != null) {
      StyleConstants.setBackground(attrSet, getBackground());
    } else {
      StyleConstants.setBackground(attrSet, textPane.getBackground());
    }
    if (getForeground() != null) {
      StyleConstants.setForeground(attrSet, getForeground());
    } else {
      StyleConstants.setForeground(attrSet, textPane.getForeground());
    }
    Font font;
    if (getFont() != null) {
      font = getFont();
    } else {
      font = textPane.getFont();
    }
    StyleConstants.setFontFamily(attrSet, font.getFamily());
    StyleConstants.setItalic(attrSet, font.isItalic());
    StyleConstants.setBold(attrSet, font.isBold());
    StyleConstants.setFontSize(attrSet, font.getSize());
    return attrSet;
  }

}

第一个类( TextPaneDefaultTreeCellRenderer )的问题是使用 nimbus LAF nullpointerexception,但还有另一个LAF, aqua metal motif gtk windows 呈现。

然后尝试进行分而治之,这个问题不是关于失败的原因吗?,否则我的班级实施得很好吗?

Discover Reason of NullPointerException in Java Native Classes, SynthTreeUI using LAF Nimbus

1 个答案:

答案 0 :(得分:0)

  

第一个类(TextPaneDefaultTreeCellRenderer)的问题是使用nimbus LAF的nullpointerexception,...

即使在我的环境(1.8.0_181,Windows 10)中使用NimbusLookAndFeel时,NullPointerException也不会发生TextPaneDefaultTreeCellRenderer ...

  

该文件夹被省略

JTextPane中为图标布局JLabelJPanel并将其用作TreeCellRenderer会很好。

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.logging.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.tree.*;

public class TextPaneTreeCellRendererTest {
  public Component makeUI() {
    JTree tree0 = new JTree(makeModel());

    // JTree tree1 = new JTree(makeModel());
    // tree1.setCellRenderer(new TextPaneDefaultTreeCellRenderer());

    // JTree tree2 = new JTree(makeModel());
    // tree2.setCellRenderer(new TextPaneTreeCellRenderer());

    // JTree tree3 = new JTree(makeModel());
    // tree3.setCellRenderer(new TreeCellRendererTextPane());

    JTree tree = new JTree(makeModel());
    tree.setRowHeight(24);
    tree.setCellRenderer(new CustomTreeCellRenderer());

    JTabbedPane tabs = new JTabbedPane();
    tabs.add("DefaultTreeCellRenderer", new JScrollPane(tree0));
    // tabs.add("TextPaneDefaultTreeCellRenderer", new JScrollPane(tree1));
    // tabs.add("TextPaneTreeCellRenderer", new JScrollPane(tree2));
    // tabs.add("TreeCellRendererTextPane", new JScrollPane(tree3));
    tabs.add("CustomTreeCellRenderer", new JScrollPane(tree));
    return tabs;
  }
  private static TreeModel makeModel() {
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("/Users/");
    DefaultMutableTreeNode parent;

    parent = new DefaultMutableTreeNode("<html>/Users/...<span style='color:red'>colors: <span style='color:blue'>blue");
    root.add(parent);
    String txt = "<html><span style='color:red'>Line 6</span> : <span style='color:blue'>!!!!!!!! on <span style='Color:green'>CentOS</span> 7</span>";
    parent.add(new DefaultMutableTreeNode(txt));
    parent.add(new DefaultMutableTreeNode(new DecoratedText("blue", Color.BLUE)));
    parent.add(new DefaultMutableTreeNode(new DecoratedText("pink", Color.PINK)));
    parent.add(new DefaultMutableTreeNode(new DecoratedText("red", Color.RED)));
    return new DefaultTreeModel(root);
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      try {
        UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
      } catch (Exception e) {
        e.printStackTrace();
      }
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new TextPaneTreeCellRendererTest().makeUI());
      f.setSize(640, 480);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class DecoratedText {
  private String text;
  private Color background; // = new JLabel().getBackground();
  private Color foreground; // = new JLabel().getForeground();
  private Font font; // = new JLabel().getFont();

  public DecoratedText(String text) {
    this.text = text;
  }

  public DecoratedText(String text, Font font) {
    this.text = text;
    this.font = font;
  }

  public DecoratedText(String text, Color foreground) {
    this.text = text;
    this.foreground = foreground;
  }

  public DecoratedText(String text, Color foreground, Font font) {
    this.text = text;
    this.foreground = foreground;
    this.font = font;
  }

  public DecoratedText(Color background, String text) {
    this.background = background;
    this.text = text;
  }

  public DecoratedText(Color background, String text, Font font) {
    this.background = background;
    this.text = text;
    this.font = font;
  }

  public DecoratedText(Color background, String text, Color foreground) {
    this.background = background;
    this.text = text;
    this.foreground = foreground;
  }

  public DecoratedText(Color background, String text, Color foreground, Font font) {
    this.background = background;
    this.text = text;
    this.foreground = foreground;
    this.font = font;
  }

  public String getText() {
    return text;
  }

  public void setText(String text) {
    this.text = text;
  }

  public Color getBackground() {
    return background;
  }

  public void setBackground(Color background) {
    this.background = background;
  }

  public Color getForeground() {
    return foreground;
  }

  public void setForeground(Color foreground) {
    this.foreground = foreground;
  }

  public Font getFont() {
    return font;
  }

  public void setFont(Font font) {
    this.font = font;
  }

  @Override
  public String toString() {
    return "DecoratedText{" + "text=" + text + ", background=" + background
           + ", foreground=" + foreground + ", font=" + font + "}";
  }

  public SimpleAttributeSet getAttributeSet(JTextPane textPane) {
    SimpleAttributeSet attrSet = new SimpleAttributeSet();
    if (getBackground() != null) {
      StyleConstants.setBackground(attrSet, getBackground());
    } else {
      StyleConstants.setBackground(attrSet, textPane.getBackground());
    }
    if (getForeground() != null) {
      StyleConstants.setForeground(attrSet, getForeground());
    } else {
      StyleConstants.setForeground(attrSet, textPane.getForeground());
    }
    Font font;
    if (getFont() != null) {
      font = getFont();
    } else {
      font = textPane.getFont();
    }
    StyleConstants.setFontFamily(attrSet, font.getFamily());
    StyleConstants.setItalic(attrSet, font.isItalic());
    StyleConstants.setBold(attrSet, font.isBold());
    StyleConstants.setFontSize(attrSet, font.getSize());
    return attrSet;
  }
}

class CustomTreeCellRenderer extends JPanel implements TreeCellRenderer {
  private DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
  private final JLabel icon = new JLabel();
  private final JTextPane textPane = new JTextPane();

  protected CustomTreeCellRenderer() {
    super(new BorderLayout());
    textPane.setContentType("text/html");
    textPane.setEditable(false);
    textPane.setOpaque(false);
    icon.setOpaque(false);
    setOpaque(false);
    add(icon, BorderLayout.WEST);
    add(textPane);
  }
  @Override public Component getTreeCellRendererComponent(
      JTree tree, Object value, boolean selected, boolean expanded,
      boolean leaf, int row, boolean hasFocus) {
    JLabel l = (JLabel) renderer.getTreeCellRendererComponent(
        tree, value, selected, expanded, leaf, row, hasFocus);

    Color bgColor;
    Color fgColor;
    if (selected) {
      bgColor = renderer.getBackgroundSelectionColor();
      fgColor = renderer.getTextSelectionColor();
    } else {
      bgColor = Optional.ofNullable(renderer.getBackgroundNonSelectionColor())
        .orElse(renderer.getBackground());
      fgColor = Optional.ofNullable(renderer.getTextNonSelectionColor())
        .orElse(renderer.getForeground());
    }

    UIDefaults defaults = new UIDefaults();
    defaults.put("TextPane[Enabled].backgroundPainter", bgColor);
    textPane.putClientProperty("Nimbus.Overrides", defaults);
    textPane.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
    textPane.setBackground(bgColor);
    textPane.setForeground(fgColor);

    DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
    Object object = node.getUserObject();
    textPane.setText("");
    Document doc = textPane.getStyledDocument();
    if (object instanceof DecoratedText) {
      DecoratedText decText = (DecoratedText) object;
      try {
        doc.insertString(doc.getLength(), decText.getText(), decText.getAttributeSet(textPane));
      } catch (BadLocationException ex) {
        ex.printStackTrace();
      }
    } else if (object instanceof DecoratedText[]) {
      DecoratedText[] arrayDecText = (DecoratedText[]) object;
      for (DecoratedText decText : arrayDecText) {
        try {
          doc.insertString(doc.getLength(), decText.getText(), decText.getAttributeSet(textPane));
        } catch (BadLocationException ex) {
          ex.printStackTrace();
        }
      }
    } else {
      textPane.setText(Objects.toString(value));
    }

    icon.setIcon(l.getIcon());
    icon.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, l.getIconTextGap()));

    return this;
  }
  @Override public void updateUI() {
    super.updateUI();
    renderer = new DefaultTreeCellRenderer();
  }
}