JTextPane und Hyperlink (ohne JEditorPane)

it07006

Mitglied
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:
Java:
	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ß
 
Zuletzt bearbeitet:
Hallo, du könntest es wie folgt machen (ich habe etwas sehr ähnliches mal machen müssen...):
Java:
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
Code:
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.
 
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ß
 
Ok, hier kommt's. Ich poste nur die relevanten Methoden vom Listener. Dieser hängt direkt an der JTextPane (
Code:
editChat
).
Das Vorgehen ist so, dass beim MouseOver der Hand-Cursor (
Code:
boolean handCursor
) gesetzt wird, und man sich zugleich das Text-Element (
Code:
linkElement
) in Attributen merkt, damit man beim
Code:
mouseClicked()
weniger Arbeit hat.
Bei mir ist's aber so, dass die URL direkt angezeigt wird, d.h. in
Code:
mouseClicked()
müsstest du noch via
Code:
getAttribute()
oder so die tatsächliche URL ermitteln.
Java:
    @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
Code:
callLink()
macht einfach:
Code:
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 😉
 
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ß
 
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ß
 

Zurück
Oben