2017-04-14 4 views
4

私はいくつかのHTMLをレンダリングし、それにCSSスタイルシートを適用するためにJTextPaneを使用しようとしています。つまり、HTMLEditorKitStyleSheetクラスを使用しています。私はあなたがこのデフォルトのスタイルシートのオブジェクトを変更した場合は、アプリケーションレベルでの変更(HTMLをレンダリングするすべてのコンポーネント)を適用しているように、すべてのHTMLEditorKitsは、同じデフォルトStyleSheetインスタンスを共有することを知っています。JTextPane StyleSheetを適切に初期化する方法は、他のHTML対応コンポーネントがそのスタイルの影響を受けないようにする方法です。

しかし、私の例で私はデフォルトに基づいて自分のStyleSheetインスタンスを作成し、これを回避していたと思いました。しかし、にのみ適用されるように意図されたスタイルシートに従ってレンダリングされるJTreeと表示されているように、これは機能しません。

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

public class TextPaneCssSpill extends JFrame { 

    private JTextPane textPane; 
    private JTree tree; 
    private JSplitPane splitPane; 

    public TextPaneCssSpill() { 
     HTMLEditorKit hed = new HTMLEditorKit(); 
     StyleSheet defaultStyle = hed.getStyleSheet(); 
     StyleSheet style = new StyleSheet(); 
     style.addStyleSheet(defaultStyle); 
     style.addRule("body {font-family:\"Monospaced\"; font-size:9px;}"); 
     style.addRule("i {color:#bababa; font-size:9px;}"); // gray italic 
     hed.setStyleSheet(style); 

     textPane = new JTextPane();   
     textPane.setEditorKit(hed); 
     textPane.setDocument(hed.createDefaultDocument()); 

     DefaultMutableTreeNode root = new DefaultMutableTreeNode(new MyNode("name", "argument"), true); 
     root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false)); 
     root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false)); 
     root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false)); 
     root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false)); 

     tree = new JTree(root); 
     tree.setCellRenderer(new MyNodeTreeRenderer()); 

     setLayout(new BorderLayout()); 
     splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, textPane, tree); 
     add(splitPane); 

     pack(); 
     setLocationRelativeTo(null); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new TextPaneCssSpill().setVisible(true); 
      } 
     }); 
    } 

    private static class MyNode { 
     private final String name; 
     private final String argument; 

     public MyNode(String name, String argument) { 
      this.name = name; 
      this.argument = argument; 
     } 

     @Override 
     public String toString() { 
      return name + " " + argument; 
     }   
    } 

    private static class MyNodeTreeRenderer extends DefaultTreeCellRenderer { 

     @Override 
     public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { 
      super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); 
      if (value instanceof DefaultMutableTreeNode) { 
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; 
       if (node.getUserObject() instanceof MyNode) { 
        MyNode mynode = (MyNode) node.getUserObject(); 
        setText("<html>" + mynode.name + "&nbsp;<i>" + mynode.argument); 
       } 
      } 
      return this; 
     } 

    } 
} 

rendered example

アプリケーション全体で何のCSSのこぼれが(そのためのテキスト・ペインは、CSSによるレンダリング、まだ木にはない)がないように、どのように1は、適切に、これらのオブジェクトを初期化していますか?

注:上記画像における赤下線がこぼれの問題を示し、(いいえ、それはレンダラはない)後私が加えました。

答えて

4

私のコードの問題の一部は、HTMLEditorKit.setStyleSheet(style);を呼んでいます。これは、私が気づいていなかったのデフォルトのスタイルシートインスタンスをすべてHTMLEditorKitsに置き換えます。

/** 
    * Set the set of styles to be used to render the various 
    * HTML elements. These styles are specified in terms of 
    * CSS specifications. Each document produced by the kit 
    * will have a copy of the sheet which it can add the 
    * document specific styles to. By default, the StyleSheet 
    * specified is shared by all HTMLEditorKit instances. 
    * This should be reimplemented to provide a finer granularity 
    * if desired. 
    */ 
    public void setStyleSheet(StyleSheet s) { 
     if (s == null) { 
      AppContext.getAppContext().remove(DEFAULT_STYLES_KEY); 
     } else { 
      AppContext.getAppContext().put(DEFAULT_STYLES_KEY, s); 
     } 
    } 

    /** 
    * Get the set of styles currently being used to render the 
    * HTML elements. By default the resource specified by 
    * DEFAULT_CSS gets loaded, and is shared by all HTMLEditorKit 
    * instances. 
    */ 
    public StyleSheet getStyleSheet() { 
     AppContext appContext = AppContext.getAppContext(); 
     StyleSheet defaultStyles = (StyleSheet) appContext.get(DEFAULT_STYLES_KEY); 

     if (defaultStyles == null) { 
      defaultStyles = new StyleSheet(); 
      appContext.put(DEFAULT_STYLES_KEY, defaultStyles); 
      try { 
       InputStream is = HTMLEditorKit.getResourceAsStream(DEFAULT_CSS); 
       Reader r = new BufferedReader(
         new InputStreamReader(is, "ISO-8859-1")); 
       defaultStyles.loadRules(r, null); 
       r.close(); 
      } catch (Throwable e) { 
       // on error we simply have no styles... the html 
       // will look mighty wrong but still function. 
      } 
     } 
     return defaultStyles; 
    } 

だから何行われる必要があることは、それはデフォルト値を変更せずに、あなたのスタイルシートを返す作るためにHTMLEditorKitを拡張することです。

import java.awt.*; 
import java.io.IOException; 
import javax.swing.*; 
import javax.swing.text.*; 
import javax.swing.text.html.*; 
import javax.swing.tree.*; 

public class TextPaneCssSpill extends JFrame { 

    private JTextPane textPane; 
    private JTree tree; 
    private JSplitPane splitPane; 
    private StyleSheet style; 

    public TextPaneCssSpill() { 
     MyHTMLEditorKit hed = new MyHTMLEditorKit(); 
     StyleSheet defaultStyle = hed.getDefaultStyleSheet(); 
     style = new StyleSheet(); 
     style.addStyleSheet(defaultStyle); 
     style.addRule("body {font-family:\"Monospaced\"; font-size:9px;}"); 
     style.addRule("i {color:#bababa; font-size:9px;}"); // gray italic 
     hed.setStyleSheet(style); 

     textPane = new JTextPane();   
     textPane.setEditorKit(hed); 
     textPane.setDocument(hed.createDefaultDocument()); 
     appendHtmlToTextPane("<i>our gray italic text</i>", textPane); 

     DefaultMutableTreeNode root = new DefaultMutableTreeNode(new MyNode("name", "argument"), true); 
     root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false)); 
     root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false)); 
     root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false)); 
     root.add(new DefaultMutableTreeNode(new MyNode("name", "argument"), false)); 

     tree = new JTree(root); 
     tree.setCellRenderer(new MyNodeTreeRenderer()); 

     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setLayout(new BorderLayout()); 
     splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, textPane, tree); 
     add(splitPane); 

     pack(); 
     setLocationRelativeTo(null); 
    } 

    private void appendHtmlToTextPane(String str, JTextPane pane) { 
     Document doc = pane.getDocument(); 
     if (doc != null) { 
      if (doc instanceof HTMLDocument) { 
       HTMLDocument htmlDoc = (HTMLDocument) doc; 
       Element html = htmlDoc.getDefaultRootElement(); 
       if (HTML.Tag.HTML.toString().equalsIgnoreCase(html.getName())) { 
        Element body = null; 
        for (int i = 0; i < html.getElementCount(); i++) { 
         Element element = html.getElement(i); 
         if (element.getAttributes().getAttribute(StyleConstants.NameAttribute) == HTML.Tag.BODY) { 
          body = element; 
          break; 
         } 
        } 
        if (HTML.Tag.BODY.toString().equalsIgnoreCase(body.getName())) { 
         try {        
          htmlDoc.insertBeforeEnd(body, str); 
          Element lastLine = body.getElement(body.getElementCount() - 1); 
          int end = lastLine.getStartOffset(); 
          textPane.setCaretPosition(end); 

         } catch (BadLocationException e) { 
         } catch (IOException ex) { 
         } 
        } 
       } 
      } 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new TextPaneCssSpill().setVisible(true); 
      } 
     }); 
    } 

    private static class MyNode { 
     private final String name; 
     private final String argument; 

     public MyNode(String name, String argument) { 
      this.name = name; 
      this.argument = argument; 
     } 

     @Override 
     public String toString() { 
      return name + " " + argument; 
     }   
    } 

    private static class MyNodeTreeRenderer extends DefaultTreeCellRenderer { 

     @Override 
     public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { 
      super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); 
      if (value instanceof DefaultMutableTreeNode) { 
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; 
       if (node.getUserObject() instanceof MyNode) { 
        MyNode mynode = (MyNode) node.getUserObject(); 
        setText("<html>" + mynode.name + "&nbsp;<i>" + mynode.argument); 
       } 
      } 
      return this; 
     } 

    } 

    /** 
    * Avoid setting the stylesheet for all HTMLEditorKit instances. 
    */ 
    private static class MyHTMLEditorKit extends HTMLEditorKit { 

     private StyleSheet myStyle; 

     @Override 
     public StyleSheet getStyleSheet() { 
      return myStyle == null ? super.getStyleSheet() : myStyle; 
     } 

     @Override 
     public void setStyleSheet(StyleSheet s) { 
      this.myStyle = s; 
     } 

     public StyleSheet getDefaultStyleSheet() { 
      return super.getStyleSheet(); 
     } 

     public void setDefaultStyleSheet(StyleSheet s) { 
      super.setStyleSheet(s); 
     } 

    } 
} 

fixed version

関連する問題