2011-10-12 15 views
14

でHTML入れ正しくフォーマットされたテキストでのJEditorPaneを作る:あなたはアプリが起動したら、フレーム内に表示されるすべてのテキストを選択した場合私は、問題を実証するために、このコードを持って、クリップボード

public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    frame.getContentPane().add(new JEditorPane("text/html", "Hello cruel world<br>\n<font color=red>Goodbye cruel world</font><br>\n<br>\nHello again<br>\n")); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
} 

すると、あなたはそれをコピーすることができますMS Word、AppleのPages、またはMailに貼り付けて、テキストを正しくフォーマットします。しかし、TextEdit、Smultron、Skypeチャットウィンドウなどの純粋なテキストエディタに貼り付けると、貼り付けられたすべてのコンテンツが1行に表示されます。

クリップボードにコピーされたテキストに改行を保存して貼り付けることができますか?

私は答えを取得していない後のMac OS X 10.7

+0

SwingX demoでは、我々は、ソースエリアからコードを貼り付けをサポートしていますか?他のテキストエディタに貼り付けるとどうなりますか? –

+0

@Shakedown、問題はSmultron –

+0

+1のような他のプレーンテキストエディタにあります。良い質問、回答 – mKorbel

答えて

19

に私のコードを実行しています、私は私の袖をロールアップし、研究や学習の多くをしました。解決策は、コンポーネントのカスタムTransferHandlerを作成し、HTMLテキストを手動でマッサージすることです。これをすべて処理するのは簡単ではありませんでした。これは、私が得たゼロの答えを説明することができます。ここで

は、実用的なソリューションです:

import javax.swing.*; 
import javax.swing.text.MutableAttributeSet; 
import javax.swing.text.html.HTML; 
import javax.swing.text.html.HTMLEditorKit; 
import javax.swing.text.html.parser.ParserDelegator; 
import java.awt.datatransfer.Clipboard; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.Transferable; 
import java.awt.datatransfer.UnsupportedFlavorException; 
import java.io.IOException; 
import java.io.Reader; 
import java.io.StringReader; 
import java.util.ArrayList; 

public class ScratchSpace { 

    public static void main(String[] args) { 
     final JFrame frame = new JFrame(); 
     final JEditorPane pane = new JEditorPane("text/html", "<html><font color=red>Hello</font><br>\u2663<br>World"); 
     pane.setTransferHandler(new MyTransferHandler()); 
     frame.getContentPane().add(pane); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

} 

class MyTransferHandler extends TransferHandler { 

    protected Transferable createTransferable(JComponent c) { 
     final JEditorPane pane = (JEditorPane) c; 
     final String htmlText = pane.getText(); 
     final String plainText = extractText(new StringReader(htmlText)); 
     return new MyTransferable(plainText, htmlText); 
    } 

    public String extractText(Reader reader) { 
     final ArrayList<String> list = new ArrayList<String>(); 

     HTMLEditorKit.ParserCallback parserCallback = new HTMLEditorKit.ParserCallback() { 
      public void handleText(final char[] data, final int pos) { 
       list.add(new String(data)); 
      } 

      public void handleStartTag(HTML.Tag tag, MutableAttributeSet attribute, int pos) { 
      } 

      public void handleEndTag(HTML.Tag t, final int pos) { 
      } 

      public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, final int pos) { 
       if (t.equals(HTML.Tag.BR)) { 
        list.add("\n"); 
       } 
      } 

      public void handleComment(final char[] data, final int pos) { 
      } 

      public void handleError(final String errMsg, final int pos) { 
      } 
     }; 
     try { 
      new ParserDelegator().parse(reader, parserCallback, true); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     String result = ""; 
     for (String s : list) { 
      result += s; 
     } 
     return result; 
    } 


    @Override 
    public void exportToClipboard(JComponent comp, Clipboard clip, int action) throws IllegalStateException { 
     if (action == COPY) { 
      clip.setContents(this.createTransferable(comp), null); 
     } 
    } 

    @Override 
    public int getSourceActions(JComponent c) { 
     return COPY; 
    } 

} 

class MyTransferable implements Transferable { 

    private static final DataFlavor[] supportedFlavors; 

    static { 
     try { 
      supportedFlavors = new DataFlavor[]{ 
        new DataFlavor("text/html;class=java.lang.String"), 
        new DataFlavor("text/plain;class=java.lang.String") 
      }; 
     } catch (ClassNotFoundException e) { 
      throw new ExceptionInInitializerError(e); 
     } 
    } 

    private final String plainData; 
    private final String htmlData; 

    public MyTransferable(String plainData, String htmlData) { 
     this.plainData = plainData; 
     this.htmlData = htmlData; 
    } 

    public DataFlavor[] getTransferDataFlavors() { 
     return supportedFlavors; 
    } 

    public boolean isDataFlavorSupported(DataFlavor flavor) { 
     for (DataFlavor supportedFlavor : supportedFlavors) { 
      if (supportedFlavor == flavor) { 
       return true; 
      } 
     } 
     return false; 
    } 

    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { 
     if (flavor.equals(supportedFlavors[0])) { 
      return htmlData; 
     } 
     if (flavor.equals(supportedFlavors[1])) { 
      return plainData; 
     } 
     throw new UnsupportedFlavorException(flavor); 
    } 
} 
1

はあなたのコードのポストをありがとう!私は、MLA引用を作成してワードプロセッサにコピーして貼り付けることを可能にするJNLPの下でアプリケーションを起動して実行するよう取り組んでいます。そのため、書式を保存する必要があります。

もっと簡単な方法がありますhttp://proctinator.com/citation/を参照してくださいが、私はあなたがJNLPで作業を自分のアプリケーションを取得するために、上記の実証的アプローチの並べ替えが必要になると思います。

次のコードは、制限のない環境で動作するJEditorPaneを検出します。 (そのような完全な権限を要求しなかったアプレットまたはJNLPファイルの場合のように)アプリのサンドボックスにあるときにでもコピー/ペーストが直接利用できない

JEditorPane citEditorPane; 
//user fills pane with MLA citations. 
citEditorPane.selectAll(); 
citEditorPane.copy(); 
citEditorPane.select(0, 0); 
+0

サンドボックス内のwebstartableのコピーパーミッションについては、私の非回答ですがコメントを参照してください:-) – kleopatra

3

注:これはではありません質問への回答、セキュリティ制限に関する@Thornによるコードへのコメント

デフォルトの権限(つまりnone ;-)を持つwebstartablesでは、実行時にSecurityManagerにClipboardServiceを問い合わせることができます:ユーザーに一度コピーを許可する(または許可しない)ように尋ねるダイアログがポップアップされます。これにより、textComponentのデフォルトのコピーアクションを置き換えることができます。それはテキストエディットは、単にそのようなものをレンダリングしていないことが考えられ

/** 
* Replaces the editor's default copy action in security restricted 
* environments with one messaging the ClipboardService. Does nothing 
* if not restricted. 
* 
* @param editor the editor to replace 
*/ 
public static void replaceCopyAction(final JEditorPane editor) { 
    if (!isRestricted()) return; 
    Action safeCopy = new AbstractAction() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      try { 
       ClipboardService cs = (ClipboardService)ServiceManager.lookup 
        ("javax.jnlp.ClipboardService"); 
       StringSelection transferable = new StringSelection(editor.getSelectedText()); 
       cs.setContents(transferable); 
      } catch (Exception e1) { 
       // do nothing 
      } 
     } 
    }; 
    editor.getActionMap().put(DefaultEditorKit.copyAction, safeCopy); 
} 

private static boolean isRestricted() { 
    SecurityManager manager = System.getSecurityManager(); 
    if (manager == null) return false; 
    try { 
     manager.checkSystemClipboardAccess(); 
     return false; 
    } catch (SecurityException e) { 
     // nothing to do - not allowed to access 
    } 
    return true; 
} 
関連する問題