为什么JTextPane中的超链接(标签)停留在中心(中心位置)

时间:2018-10-18 02:41:12

标签: java html swing jtextpane

我已经实现了两种方法,以便在 JTextPane 中添加文本和超链接。问题在于,超链接显示为居中对齐,但不显示文本(我希望两者都保持左对齐)。

方法是:

public void addText (String log, Color c, boolean bold) {
    StyledDocument doc = jTextPane.getStyledDocument();

    SimpleAttributeSet attrs = new SimpleAttributeSet();
    StyleConstants.setFontFamily(attrs, "Calibri");
    StyleConstants.setFontSize(attrs, 13);
    StyleConstants.setForeground(attrs, c);
    StyleConstants.setBold(attrs, bold);
    try {
        doc.insertString(doc.getLength(), log, attrs);
    } catch (BadLocationException ex) {
        Logger.getLogger(FrameLog.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public void addHyperlink (URL url, String text) {
    StyledDocument doc = jTextPane.getStyledDocument();

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

    SimpleAttributeSet attrs = new SimpleAttributeSet();
    attrs.addAttribute(HTML.Tag.A, hrefAttr);

    StyleConstants.setFontFamily(attrs, "Calibri");
    StyleConstants.setFontSize(attrs, 13);
    StyleConstants.setForeground(attrs, Color.blue);

    try {
        doc.insertString(doc.getLength(), text, attrs);
    } catch (BadLocationException e) {
        e.printStackTrace(System.err);
    }
}


结果是这样的:

the problem[1]

完整问题演示代码段HERE

有人知道我该如何解决此问题?

2 个答案:

答案 0 :(得分:1)

出于价值,我尝试处理文档中的HTML文本时会遇到一些旧的(难看的)代码。

我使用了insertString(...)以外的方法。也许这会给您一些想法?

import java.awt.*;
import java.io.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;

public class TextPaneHTML extends JFrame implements ActionListener
{
    JTextPane textPane;
    HTMLEditorKit editorKit;
    HTMLDocument doc;
    Element root;

    public TextPaneHTML()
    {
        textPane = new JTextPane();
//      textPane.setEditable( false );
        textPane.setContentType( "text/html" );
        textPane.setEditable(false);
        editorKit = (HTMLEditorKit)textPane.getEditorKit();
        doc = (HTMLDocument)textPane.getDocument();
        root = doc.getDefaultRootElement();


        DefaultCaret caret = (DefaultCaret)textPane.getCaret();
        caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
        textPane.setText( "<html><body>Hello world I want some long text <a href=\"http://answers.polldaddy.com/poll/1742928/\">Do you like polls</a> to it wraps to a new line World!</body></html>" );


//      textPane.setCaretPosition(7);
//      textPane.setText( "" );
//      printInfo();

        //  Add text pane to frame

        JScrollPane scrollPane = new JScrollPane( textPane );
        scrollPane.setPreferredSize( new Dimension( 200, 200 ) );
        getContentPane().add( scrollPane );

        //  Add a append button
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout( new GridLayout(1, 0) );
        getContentPane().add( buttonPanel, BorderLayout.SOUTH );

        createButton("Normal", buttonPanel);
        createButton("Styled", buttonPanel);
        createButton("B1", buttonPanel);
        createButton("B2", buttonPanel);
        createButton("B3", buttonPanel);


        try
        {
        HTMLDocument.Iterator it = doc.getIterator(HTML.Tag.A);

        while (it.isValid())
        {
            SimpleAttributeSet s = (SimpleAttributeSet)it.getAttributes();
            System.out.println(s);
            s.removeAttribute(HTML.Attribute.HREF);
            System.out.println( s.getClass().getName());
            String href = (String)s.getAttribute(HTML.Attribute.HREF);
            int start = it.getStartOffset();
            int end = it.getEndOffset();
            String text = doc.getText(start, end - start);
            System.out.println( href + " : " + text );
            it.next();
        }
        }
        catch(Exception e) {};

    }

    public void createButton(String text, JPanel panel)
    {
        JButton button = new JButton(text);
        button.addActionListener( this );
        panel.add( button );
    }

    public void actionPerformed(ActionEvent ae)
    {
        String command = ae.getActionCommand();
        String text;

        try
        {
            if ("Normal".equals( command ))
            {
                text = "normal text";
                editorKit.insertHTML(doc, doc.getLength(), text, 0, 0, null);
            }

            if ("Styled".equals( command ))
            {
//                  text = "<font size=5 color=red>font and color test</font>";
                text = "<a href=\"abc\">hyperlink</a>";
                editorKit.insertHTML(doc, doc.getLength(), text, 0, 0, null);
//              doc.insertString(doc.getLength(), text, null);
//              try {
//                  editorKit.read(new StringReader(text), doc, doc.getLength());
//              } catch (Exception e) {
//              e.printStackTrace();
//              }

            }

            if ("B1".equals( command ))
            {
//                  text = "<br>B1";
                text = "<a href=\"abc\">hyperlink</a>";
                Element element = root.getElement(1);
                doc.insertBeforeEnd(element, text);
            }

            if ("B2".equals( command ))
            {
                Element element = root.getElement(1);
                text = "<br>B2-after start";
                doc.insertAfterStart(element, text);
                // why doesn't this work
                text = "<br>B2-before end";
                doc.insertBeforeEnd(element, text);
            }

            if ("B3".equals( command ))
            {
//                  text = "<p>B3</p>";
//              editorKit.insertHTML(doc, textPane.getCaretPosition(), text, 0, 0, HTML.Tag.P);
                text = "<a href=\"abc\">hyperlink</a>";
                editorKit.insertHTML(doc, textPane.getCaretPosition(), text, 0, 0, HTML.Tag.A);
//              doc.insertString(doc.getLength(), text, null);
            }

        }
        catch(Exception e)
        {
//              BadLocationException ble = (BadLocationException)e;
//              System.out.println(e + " : " + ble.offsetRequested());
                System.out.println(e);
        }

//      System.out.println( command + ": -----------" );
//      System.out.println( "Elements: " + root.getElementCount() );
//      System.out.println( root.getElement(0).getAttributes() );
//      System.out.println( root.getElement(1).getAttributes() );
        try
        {
            System.out.println( "textPane: " + textPane.getText() );
            System.out.println( "Document: " + textPane.getDocument().getText(0, textPane.getDocument().getLength()) );
        }
        catch(Exception e2) {}
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
        TextPaneHTML frame = new TextPaneHTML();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setSize(50, 120);
        frame.setVisible(true);
            }
        });
    }
}

答案 1 :(得分:1)

感谢camickr's answer,我设法使用HTMLEditorKit类来找到解决方案:)

我用一个泛型替换了以前的方法,该泛型将一些html代码附加到JTextPane中。

新方法是:

    public void appendTextPane (String html) {
        HTMLEditorKit editor = (HTMLEditorKit) jTextPane.getEditorKit();
        HTMLDocument doc = (HTMLDocument) jTextPane.getDocument();
        String TAG;
        if (html.charAt(0) != '<') {
            TAG = "";
        } else {
            int nextSpaceIdx = html.indexOf(" ");
            int nextBrcktIdx = html.indexOf(">");
            TAG = html.substring(1, nextBrcktIdx < nextSpaceIdx ? nextBrcktIdx : nextSpaceIdx);
        }
//        System.out.println(jTextPane.getText());
        try {
            editor.insertHTML(doc, doc.getLength(), html.replaceAll(" ", "&#160;"), 0, 0, HTML.getTag(TAG));
        } catch (IOException | BadLocationException ex) {
        }
    }

固定的预览是这样的:

fixed result

完整的解决方案演示代码段:

import java.awt.*;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.*;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

public class SolutionDemo {

    private JFrame jFrame;
    private JTextPane jTextPane;
    private JScrollPane jScrollPane;

    public SolutionDemo () {
        //CREATE THE COMPONENTS AND SHOW THE FRAME WINDOW
        jFrame = new JFrame();
        jTextPane = new JTextPane();
        jScrollPane = new JScrollPane(jTextPane);
        jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        jFrame.setLayout(new FlowLayout());

        //I NEED IT TO BE HTML SO THE HYPERLINK TO BE CLICKABLE
        jTextPane.setContentType("text/html");
        jTextPane.setEditable(false);
        jTextPane.setPreferredSize(new Dimension(600, 100));
        jFrame.add(jScrollPane);
        jFrame.pack();
        jFrame.setVisible(true);
        jFrame.setLocationRelativeTo(null);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //ADD LISTENER IN ORDER TO OPEN THE LINK ON BROWSER WHEN CLICKED
        jTextPane.addHyperlinkListener(new HyperlinkListener() {
            public void hyperlinkUpdate (HyperlinkEvent evt) {
                if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                    if (Desktop.isDesktopSupported()) {
                        try {
                            Desktop.getDesktop().browse(evt.getURL().toURI());
                        } catch (IOException | URISyntaxException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            }
        });

    }

    public void init () {
        //SET GLOBAL STYLES
        jTextPane.setText(""
                + "<head>"
                + " <style type=\"text/css\">"
                + "     body{ "
                + "         color: green;"
                + "         font-family: calibri"
                + "     }"
                + " </style>"
                + "</head>");
        //ADD SOME TEXT AND HYPERLINKS
        String url = "https://www.example.com";
        appendTextPane("No tag must be inserted first in order to custom header work with this impl ");
        appendTextPane("<span>BLAH blah BLAH blah BLAH blah BLAH blah </span>");
        appendTextPane("<span style=\"color:red\">BLAH blah BLAH blah BLAH blah BLAH blah </span>");
        appendTextPane("<a href=\"" + url + "\">" + url + "</a>");
        appendTextPane("<span> BLAH blah BLAH blah BLAH blah BLAH blah <a href=\"" + url + "\">" + url + "</a></span>");
        appendTextPane("With no tag the text goes to next line <a href=\"" + url + "\">" + url + "</a>");
    }

    public void appendTextPane (String html) {
        HTMLEditorKit editor = (HTMLEditorKit) jTextPane.getEditorKit();
        HTMLDocument doc = (HTMLDocument) jTextPane.getDocument();
        String TAG;
        if (html.charAt(0) != '<') {
            TAG = "";
        } else {
            int nextSpaceIdx = html.indexOf(" ");
            int nextBrcktIdx = html.indexOf(">");
            TAG = html.substring(1, nextBrcktIdx < nextSpaceIdx ? nextBrcktIdx : nextSpaceIdx);
        }
//        System.out.println(jTextPane.getText());
        try {
            //REPLACE SPACES WITH ITS NUMERIC ENTITY REFERENCE IN ORDER TO SHOW ALL THE EXISTING SPACES 
            editor.insertHTML(doc, doc.getLength(), html.replaceAll(" ", "&#160;"), 0, 0, HTML.getTag(TAG));
        } catch (IOException | BadLocationException ex) {
        }
    }

    public static void main (String[] args) {
        new SolutionDemo().init();
    }
}

谢谢camickr不幸的是,由于缺乏声誉,我无法接受您的回答。