# JTextPane und Hyperlink (ohne JEditorPane)



## it07006 (24. Apr 2010)

Hallo,

ich muss im Rahmen meines Studiums einen kleinen HTML Browser in Java schreiben. Bisher funktioniert alles bis auf das Hinzufügen eines Hyperlinks in meine JTextPane. (Ich weiß die JEditorPane kann html schon nativ aber die dürfen wir für das Projekt nicht verwenden). Ich habe schon viel gegoogelt und auch hier im Forum gesucht, allerdings nichts zum Laufen bekommen. Kann mir jemand weiterhelfen?

Mein Ansatz:

```
public void addHyperlink(String url, String text) {
		  try {
		    // First, setup the href attribute for <A> tag.
		    SimpleAttributeSet hrefAttr = new SimpleAttributeSet();
		    hrefAttr.addAttribute(HTML.Attribute.HREF, url);

		    // Second, setup the <A> tag
		    SimpleAttributeSet attrs = new SimpleAttributeSet();
		    attrs.addAttribute(HTML.Tag.A, hrefAttr);
		    // Add the text along with its attributes.
		    setText(attrs, text);
		  }
		  catch (BadLocationException e) {
		    e.printStackTrace(System.err);
		  }        
		}
```

Gruß


----------



## KrokoDiehl (26. Apr 2010)

Hallo, du könntest es wie folgt machen (ich habe etwas sehr ähnliches mal machen müssen...):

```
public void addHyperlink(String url, String text) 
{
    try 
    {
        String insertText = text;
        if (text == null || text.isEmpty())
            insertText = url;

        SimpleAttributeSet urlAttrs = new SimpleAttributeSet();
        urlAttrs.addAttribute(HTML.Attribute.HREF, url);

        StyleConstants.setForeground(urlAttrs, Color.blue);
        StyleConstants.setFontUnderline(urlAttrs, true);

        myDocument.insertString(
            myDocument.getLength(),
            insertText,
            urlAttrs);
    }
    catch (BadLocationException e) 
    {}        
}
```
Das sorgt dafür, dass ein Link wie ein Link aussieht, sofern 
	
	
	
	





```
myDocument
```
das Dokument deiner Textpane ist.
ABER, das sorgt noch nicht für das gewohnte Verhalten. Das musst du -vermutlich- selbst programmieren. 
Auch hierzu hätte ich etwas, das über MouseListener arbeitet. Ich weiß aber nicht, ob es wirklich das ist, was du willst.


----------



## it07006 (26. Apr 2010)

Hallo KrokoDiehl,

schonmal vielen Dank für deine Antwort. Die Lösung über den MouseListener würde mich auch interessieren, es wäre genau das, was ich suche. Also wenn du das auch noch posten könntest, wäre ich dir sehr dankbar.

Gruß


----------



## KrokoDiehl (26. Apr 2010)

Ok, hier kommt's. Ich poste nur die relevanten Methoden vom Listener. Dieser hängt direkt an der _JTextPane _(
	
	
	
	





```
editChat
```
).
Das Vorgehen ist so, dass beim MouseOver der Hand-Cursor (
	
	
	
	





```
boolean handCursor
```
) gesetzt wird, und man sich zugleich das Text-Element (
	
	
	
	





```
linkElement
```
) in Attributen merkt, damit man beim 
	
	
	
	





```
mouseClicked()
```
 weniger Arbeit hat.
Bei mir ist's aber so, dass die URL direkt angezeigt wird, d.h. in 
	
	
	
	





```
mouseClicked()
```
 müsstest du noch via 
	
	
	
	





```
getAttribute()
```
 oder so die tatsächliche URL ermitteln.

```
@Override
    public void mouseMoved( MouseEvent event )
    {
        if (event == null)
            return;
        if (event.isConsumed())
            return;
        if ( ! editChat.equals(event.getComponent()))
            return;
        
        // das Text-Element an der Mouse-Position ermitteln
        int     pos  = editChat.viewToModel( event.getPoint() );
        Element elem = ((StyledDocument) editChat.getDocument()).getCharacterElement(pos);
        if (elem != null)
        {
            AttributeSet set = elem.getAttributes();
            if (set != null)
            {
                // Ok ... ich erkenne einen Link daran, dass er unterstrichen ist ;)
                Object  attr   = set.getAttribute(StyleConstants.Underline);
                boolean isLink = (attr != null && attr.equals(Boolean.TRUE));
                
                if (isLink && ! handCursor)
                {
                    handCursor  = true;
                    linkElement = elem;
                    editChat.setCursor( Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) );
                } //if Hand-Cursor setzen
                else if ( ! isLink && handCursor)
                {
                    handCursor  = false;
                    linkElement = null;
                    editChat.setCursor( Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR) );
                } //if normalen Cursor setzen
            } //if Attribute
        } //if Element
    } //void mouseMoved(MouseEvent)

    @Override
    public void mouseClicked( MouseEvent event )
    {
        if (event == null)
            return;
        if (event.isConsumed())
            return;
        if (linkElement == null)
            return;
        if ( ! SwingUtilities.isLeftMouseButton(event))
            return;
        if (event.getClickCount() > 1)
            return;
        if ( ! editChat.equals(event.getComponent()))
            return;
        
        try
        {
            String url = editChat.getDocument().getText(
                    linkElement.getStartOffset(),
                    linkElement.getEndOffset()-linkElement.getStartOffset());
            //hier müsstest du über die Textattribute von linkElement an die URL kommen
            this.callLink(url);
        } //try
        catch (BadLocationException BLexc)
        {}
    } //mouseClicked(MouseEvent)
```

Das 
	
	
	
	





```
callLink()
```
 macht einfach:

```
Desktop.getDesktop().browse( new java.net.URI(urlString) );
```
 mit etwas Fehlerabfrage usw.
Was außerdem fehlt ist, dass einmal geklickte Links anders gefärbt werden (meistens lila), aber das kann man nach Bedarf auch noch einarbeiten.

...letztlich muss man aber feststellen, dass das ganze mit einer _JEditorPane _und einem _HyperLinkListener _wesentlich bequemer vonstatten ginge


----------



## it07006 (26. Apr 2010)

Hallo KrokoDiehl,

danke für die schnelle Antwort. Ich werde es heute noch ausprobieren und mein Ergebnis posten. Eine EditorPane ist fast immer die bessere Wahl, allerdings wurde sie für dieses Projekt verboten, da sie ja schon nativ HTML interpretieren kann.

Gruß


----------



## it07006 (5. Mai 2010)

So, etwas spät ich weiß, aber das Studium war stressig. Also ich habe es probiert und es funktioniert wunderbar. Ein kleiner Makel ist noch, wenn man die Maus zwischen dem Klicken auf den Link nicht bewegt, dann passiert auch nicht, aber das finde ich nicht so schlimm. 
Danke nochmal an KrokoDiehl.

Wer den Code haben möchte soll sich einfach melden.

Gruß


----------

