2013-03-27 14 views
5

私は文字と記号を表示するのにJTextPaneを使用しています。後者はカスタムJComponentsで表されます。たとえば、テキストペインに次のような文字が表示されることがあります。 enter image description here テキストペインはユーザーが編集可能で、ボタンを使用して任意の位置に、選択したテキストの代わりにシンボルを追加できます。私はこれをJTextPane.insertComponent()メソッドで行います。アプリケーションのある時点で、テキストペインに現在表示されている内容を知る必要があります。これは、入力されたテキストだけでなく、その中に含まれる正確なコンポーネントも意味します。JTextPaneからjavax.swing.text.Elementを介してコンポーネントを取得しますか?

PositionsDocumentListenersで大規模なトラブルが発生しましたが、私のテキストペインの内容を管理していましたが、解決していた以上の問題が続きました。だから私は最終的に、私の悩みはおそらく私の部分の設計上の不具合によると判断したので、私はテキストペインを介して自分のコンポーネントに到達できない場合、私は見ることにしました。

AbstractDocumentとその他の関連クラスのドキュメントとソースコードを検索すると、インターフェイスjavax.swing.text.Elementが見つかりました。私はその後、私のアプリケーションの出力聞かせてくれました

for(int i = 0; i < textPane.getDocument().getLength(); i++) { 
    System.out.println(((StyledDocument) textPane.getDocument()).getCharacterElement(i)); 
} 

LeafElement(コンテンツ)0,4

LeafElement(コンテンツ)0,4

LeafElement(コンテンツ)0を、4

リーフエレメント(内容)0,4

LeafElement(成分)4,5-

LeafElement(コンテンツ)5,9

LeafElement(コンテンツ)5,9

LeafElement(コンテンツ)5,9

LeafElement(コンテンツ) 5,9

LeafElement(成分)9,10

その見私が得たには、Documentのどの位置に何が表示されているのかについて何らかの情報があるようですが、その位置で実際のコンテンツを取得することができるはずです。別の30分を検索した後、それぞれの要素がどのように表現されているかを調べると、私はここで質問を投稿し、あなたの中にはこれを達成する方法を知りたいと思っていました。私が見た

この誰かが実際JTextPaneに含まれる成分の正確な数を有する成分の配列を返しtextPane.getComponents()を通じてコン​​ポーネントにアクセスしようと、彼らは明らかのあるタイプjavax.swing.text.ComponentView$Invalidatorの全てであるquestion私には役に立たない。元のタイプのシンボルへのキャストが機能しないため、ここから正しく続ける方法がわかりません。

TL; DR

はどうすればJTextPaneのテキスト、およびテキスト・ペインからその位置の内側にあるJComponentを得るのですか?

+0

うまくいけば、この[回答](http://stackoverflow.com/a/10463120/1057230)は、ポジショニングに関するいくつかのアイデアを提供するのに役立ちます。 +1注目:-) –

+0

@Gagandeep Bali注目してくれてありがとう:-)。あなたの答えは面白いですが、不幸にも、コンポーネントの 'Location'を知る必要はなく、テキスト内のインデックスとしてas-inの位置を知る必要があるので、私の問題には当てはまりません。しかし、コンポーネント自体にアクセスできない場合、私の目標に絶対に必要なものはすべて無駄です。 – nfs

+0

Ahha、この知識はまだ私の把握の範囲外です。知恵を持って欲しい人、すぐに話題に光を入れられるようにしてください:-)最高の恋人... –

答えて

10

以下に示すように、テキストペインのStyledDocumentをトラバースして、コンポーネントまたはアイコンを表す要素を見つけることができます。

image

 
BranchElement(section) 0,7 

BranchElement(paragraph) 0,7 

LeafElement(content) 0,4 

LeafElement(icon) 4,5 

class javax.swing.plaf.IconUIResource 
LeafElement(component) 5,6 

class javax.swing.JLabel 
LeafElement(content) 6,7 

SSCCE:あなたがComponentViewのから見ることができるよう

/** 
* @see http://stackoverflow.com/a/15669307/230513 
* @see http://stackoverflow.com/questions/2883413 
*/ 
public class DocumentParse { 

    private static final String ELEM = AbstractDocument.ElementNameAttribute; 
    private static final String ICON = StyleConstants.IconElementName; 
    private static final String COMP = StyleConstants.ComponentElementName; 

    public static void main(String args[]) throws Exception { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JTextPane jtp = new JTextPane(); 
     StyledDocument doc = (StyledDocument) jtp.getDocument(); 
     SimpleAttributeSet normal = new SimpleAttributeSet(); 
     StyleConstants.setFontFamily(normal, "Serif"); 
     StyleConstants.setFontSize(normal, 72); 
     StyleConstants.setForeground(normal, Color.blue); 
     doc.insertString(doc.getLength(), "Test", normal); 
     jtp.setSelectionStart(doc.getLength()); 
     jtp.insertIcon(UIManager.getIcon("OptionPane.warningIcon")); 
     jtp.setSelectionStart(doc.getLength()); 
     jtp.insertComponent(new JLabel("Label")); 
     jtp.setSelectionStart(doc.getLength()); 

     ElementIterator iterator = new ElementIterator(doc); 
     Element element; 
     while ((element = iterator.next()) != null) { 
      System.out.println(element); 
      AttributeSet as = element.getAttributes(); 
      if (as.containsAttribute(ELEM, ICON)) { 
       System.out.println(StyleConstants.getIcon(as).getClass()); 
      } 
      if (as.containsAttribute(ELEM, COMP)) { 
       System.out.println(StyleConstants.getComponent(as).getClass()); 
      } 
     } 

     f.add(jtp); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 
} 
+0

これは私が探していた答えの一種です! 'JTextPane'の中の全てを' Elements'を通してアクセスすることが可能でなければならないことを知っていました。フォローアップの質問:1. 'StyleConstants.ComponentElementName'の' AttributeSet'を尋ねる必要があることを知りたいのですが、このような文字列定数を探す場所を知るにはどうすればいいですか? 2.なぜElementIteratorはドキュメントの内容の後ろに改行文字を与えますか? (textPane.getDocument.getLength()が '12'を返すのに' LeafElement(content)12,13'を取得します!) – nfs

+0

@SheridanVespo:1.正直なところ、私は 'getAttributeNames()'を列挙し、名前付き定数。 2. AbstractDocument#toString()の礼儀。 – trashgod

+0

1.ありがとう、多分私の今後の問題に役立つだろう。 2.'AbstractDocument'は 'toString()'メソッドを持っていません!少なくとも[grepcode](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/javax/swing/text/AbstractDocument.java#AbstractDocument)によるとは限りません。 – nfs

4

元のコンポーネントは、javax.swing.text.ComponentView$Invalidatorの最初の(そして唯一の)子です。

無効化プログラムのリストを取得し、その子プログラムを使用して挿入されたコンポーネントにアクセスすることができます。

+0

私はこれがどのようにうまくいったのだろうか? – trashgod

+0

ComponentViewのソースを参照してください。実際には、レイアウトビューのアクションsetComponentParentが呼び出されます。それはコードを持っていますvoid setComponentParent(){ \t View p = getParent(); \t if(p!= null){ \tコンテナparent = getContainer(); \t場合(親= nullを!){ \t \t(C == null)の場合は{ \t \t //コンポーネント \t \tコンポーネントのcomp =にcreateComponentを(構築しよう)。 \t \t if(comp!= null){ \t \t \t createdC = comp; \t \t \t c = new Invalidator(comp); \t \t} \t \t} – StanislavL

関連する問題