2013-03-27 15 views
5

Sto usando un JTextPane per visualizzare caratteri e simboli, dove questi ultimi sono rappresentati da colori personalizzati JComponents. Ad esempio, il riquadro di testo potrebbe mostrare qualcosa del tipo: enter image description here Il riquadro di testo è modificabile dall'utente ed è consentito all'utente di aggiungere più simboli tramite un pulsante in qualsiasi posizione e in sostituzione del testo selezionato. Lo faccio tramite il metodo JTextPane.insertComponent(). Ad un certo punto dell'applicazione devo sapere cosa viene visualizzato nel riquadro di testo, e con questo intendo non solo il testo inserito, ma anche i componenti esatti contenuti all'interno.Ottieni un componente da un JTextPane tramite javax.swing.text.Element?

Sono passato attraverso numerosi problemi con Positions e DocumentListeners per gestire il contenuto del mio riquadro di testo, ma ho continuato a causare più problemi di quanti ne stavo risolvendo. Ecco perché alla fine ho deciso che i miei problemi sono probabilmente dovuti a un errore di progettazione da parte mia, quindi ho deciso di vedere se non riesco ad accedere ai miei componenti attraverso il pannello di testo.

Ricerca nella documentazione e nel codice sorgente di AbstractDocument e in altre classi correlate, ho trovato l'interfaccia javax.swing.text.Element. Poi ho lasciato la mia uscita applicazione

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

che mi ha dato:

LeafElement (contenuto) 0,4

LeafElement (contenuto) 0,4

LeafElement (contenuto) 0 , 4

LeafElement (contenuto) 0,4

LeafElement (componente) 4,5

LeafElement (contenuto) 5,9

LeafElement (contenuto) 5,9

LeafElement (contenuto) 5,9

LeafElement (contenuto) 5,9

LeafElement (componente) 9,10

Visto che il LeafElements che ho ottenuto sembrano avere qualche tipo di informazione su ciò che viene visualizzato in quale posizione nel Document, ho pensato che deve essere possibile ottenere il contenuto effettivo in quella posizione. Dopo aver cercato per un'altra mezz'ora come rappresentare il contenuto di ognuno degli elementi, ho rinunciato e ho deciso di postare la mia domanda qui, sperando che alcuni di voi potessero sapere come ottenerlo !?

Ho visto questo question cui qualcuno tenta di accedere ai componenti attraverso textPane.getComponents(), che restituisce un array di componenti con il numero esatto di componenti effettivamente contenuti nel JTextPane, ma sono tutti di tipo javax.swing.text.ComponentView$Invalidator, che è ovviamente di inutile per me. Forse non vedo come continuare correttamente da qui, perché un cast per il tipo originale del mio simbolo non funziona.

tl; dr

Come faccio ad avere un JComponent, che si trova all'interno del testo di un JTextPane, e la sua posizione dal riquadro di testo?

+0

Speriamo che questo [risposta] (http://stackoverflow.com/a/10463120/1057230), potrebbe in grado di contribuire a fornire qualche idea per quanto riguarda il posizionamento thingy. +1 per più attenzione :-) –

+0

@Gagandeep Bali Grazie per l'attenzione :-). La tua risposta è interessante, ma sfortunatamente non si applica al mio problema, perché non ho bisogno di conoscere la 'Location' del componente, ma piuttosto la posizione as-in: index all'interno del testo. Tutto ciò è comunque inutile, se non riesco ad accedere al componente stesso, che è assolutamente necessario per il mio scopo. – nfs

+0

Ahha, questa conoscenza è al di là della mia comprensione, per ora. Desideri qualcuno con saggezza, essere in grado di mettere presto in luce l'argomento :-) MEGLIO DI FORTUNA ... –

risposta

10

si può attraversare il riquadro del StyledDocument testo per trovare gli elementi che rappresentano i componenti o icone, come mostrato di seguito.

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:

/** 
* @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

Ora, QUESTO è il tipo di risposta che stavo cercando! Sapevo che doveva essere possibile accedere a tutto nel 'JTextPane' tramite' Elements', non riuscivo a capire come. Domande successive: 1. Come faccio a sapere che devo chiedere a 'AttributeSet' di' StyleConstants.ComponentElementName', cioè come faccio a sapere dove cercare questo tipo di costanti di stringa? 2. Perché 'ElementIterator' mi fornisce un nuovo carattere di linea dopo il contenuto del documento? (Ottengo 'LeafElement (tenore) 12,13' anche se' textPane.getDocument.getLength() '' 12' rendimenti!) – nfs

+0

@SheridanVespo: 1. Onestamente, ho enumerato 'getAttributeNames()' e cercato le API per la costanti nominate. 2. Per gentile concessione di 'AbstractDocument # toString()'. – trashgod

+0

1. Grazie, forse questo mi aiuterà con i problemi futuri che ho. 2.'AbstractDocument' non ha un metodo 'toString()' !? Almeno non secondo [grepcode] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/javax/swing/text/AbstractDocument.java#AbstractDocument). – nfs

4

Il componente originale è il primo (e unico) figlio della javax.swing.text.ComponentView$Invalidator come si può vedere da ComponentView.

È possibile ottenere l'elenco dei invalidators e utilizzare i loro figli a acccess componenti inseriti.

+0

I _wondered_ come ha funzionato! – trashgod

+0

Vedere le origini di ComponentView. In effetti sulla vista del layout viene chiamata la funzione setComponentParent.Ha il codice void setComponentParent() { \t Visualizza p = getParent(); \t if (p! = Null) { \t Contenitore parent = getContainer(); \t se (genitore! = Null) { \t \t if (c == null) {// \t \t cercare di costruire un componente \t \t Component comp = createComponent(); \t \t if (comp! = Null) { \t \t \t createdC = comp; \t \t \t c = nuovo Invalidator (comp); \t \t} \t \t} – StanislavL

Problemi correlati