【问题标题】:Proper manner create Class, JTree, DefaultTreeCellRenderer using JTextPane使用 JTextPane 正确创建 Class、JTree、DefaultTreeCellRenderer
【发布时间】:2018-08-19 01:19:39
【问题描述】:

我有这个类是为了使用 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;
  }

}

替代类是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;
  }
}

如你所见(不是叶子没有正确显示,文件夹被省略,单词只显示第一个字母)

我的另一个班级是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) 的问题是这个 nullpointerexception 使用 nimbus LAF,但使用另一个 LAF,aqua、metalmotifgtkwindows都没有出现问题。

并且尝试分而治之,这个问题不是关于什么失败了? 否则我的课程实施得很好吗?

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

【问题讨论】:

    标签: java swing jtree jtextpane nimbus


    【解决方案1】:

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

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

    文件夹被省略

    JPanel 中为图标布局JTextPaneJLabel 并将其用作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();
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-10-05
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 2019-01-31
      • 2017-09-14
      • 1970-01-01
      • 2012-09-23
      • 2021-02-19
      相关资源
      最近更新 更多