获取 JTextPane 中选中文本的标签

Get the tags of selected text in JTextPane

早上好亲爱的, 我有一个内容类型为 'text/html' 的 JTextPane。在此 JTextPane 中,我加载了圣经,其中诗句由标签分隔。我想要做的是在用户单击文档的一部分时确定所选的诗集。 从现在开始,我可以使用方法 getSelectedText() 获取选定的文本。但是结果不包含原始文档的标签,这可以帮助我检测包含所选文本的诗集的开头或结尾。

我无法进行简单的搜索,因为方法 getSelectedText() return 没有标签的文本。例如

的结果
Abraham eut pour descendant <g v=\"Isaac\">Isaac</g>.

将是"Abraham eut pour descendant Isaac." 所以,如果我进行简单的搜索,我将一无所获。 综上所述,我想知道如何获取所选文本的标签,以便我可以确定所选文本的诗集。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

public class VersetBibliques {

    Rectangle[] rects = new Rectangle[2];
    HTMLEditorKit kit;
    HTMLDocument htmlDoc;    

    private JPanel getContent() {
        rects[0] = new Rectangle();
        rects[1] = new Rectangle();
        JPanel panel = new JPanel(new GridLayout(1, 0, 10, 0));
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        panel.add(new JScrollPane(getTextPane()));
        return panel;
    }

    private JTextPane getTextPane() {
        JTextPane textPane = new JTextPane();
        kit = new HTMLEditorKit();
        htmlDoc = new HTMLDocument();
        textPane.setEditable(false);

        textPane.setEditorKit(kit);
        textPane.setDocument(htmlDoc);
        textPane.setContentType("text/html");
        textPane.setBackground(Color.WHITE);
        textPane.setFont(new Font("Arial Bold", Font.ITALIC, 38));
        try {
            kit.insertHTML(htmlDoc, 0, text, 0, 0, null);                
        } catch (BadLocationException e) {
            System.out.println("bad location: " + e.getMessage());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        textPane.addMouseListener(selector);
        Style s = htmlDoc.addStyle("logical", null);
        StyleConstants.setFontFamily(s, "georgia");
        StyleConstants.setFontSize(s, 58);
        s = htmlDoc.addStyle("lineSpace", null);
        StyleConstants.setLineSpacing(s, 0.25f);
        htmlDoc.setLogicalStyle(0, htmlDoc.getStyle("logical"));
        return textPane;
    }

    public static void main(String[] args) {
        VersetBibliques test = new VersetBibliques();
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(test.getContent());
        f.setSize(600, 400);
        f.setLocation(200, 200);
        f.setVisible(true);
    }

    private MouseListener selector = new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            try {
                JTextPane textPane = (JTextPane) e.getComponent();
                int start = textPane.getSelectionStart() - 10;
                int end = textPane.getSelectionEnd() + 10;

                textPane.setSelectionEnd(end);
                textPane.setSelectionStart(start);

                String selectedText = textPane.getSelectedText();
                System.out.println("text content : " + selectedText);//Il faudra faire le test avec Jean 11:35
                System.out.println("start: "+start+"- end:"+end);


            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    };

    String text = "<mt>Évangile selon Matthieu</mt>\n"
            + "<c><cn>1</cn>\n"
            + "<mt>Naissance et enfance de Jésus</mt><s>La généalogie de Jésus</s><r>(<ref v=\"LUK3.23-38\">Lc 3.23-38</ref>)</r><v><vn>1</vn>Voici la généalogie de Jésus-Christ, de la descendance de <g v=\"David\">David</g> et d'<g v=\"Abraham\">Abraham</g>. </v>"
            + "<p/><v><q><vn>2 </vn>Abraham eut pour descendant <g v=\"Isaac\">Isaac</g>.<br/>Isaac eut pour descendant <g v=\"Jacob\">Jacob</g>.<br/>Jacob eut pour descendant <g v=\"Juda\">Juda</g> et ses frères.</q></v>"
            + "<v><q><vn>3 </vn>De Thamar, Juda eut pour descendant Péretz et Zérah.<br/>Péretz eut pour descendant Hetsrom.<br/>Hetsrom eut pour descendant Aram.</q></v>"
            + "<v><q><vn>4 </vn>Aram eut pour descendant Aminadab.<br/>Aminadab eut pour descendant Nahchôn,<br/>Nahchôn eut pour descendant Salma.</q></v>"
            + "<v><q><vn>5 </vn>De Rahab, Salma eut pour descendant Booz.<br/>De Ruth, Booz eut pour descendant Obed.</q></v></c>";

}

提前致谢

要从文档中读取 html,您需要使用 HTMLEditorKit。特别是 write 方法。

要获得选区偏移量,您需要使用 getSelectionStartgetSelectionEnd,或者只是 getCaretPosition,来自 JTextPane

要获取围绕这些偏移量的标记,您可以使用 HTMLDocument 中的 getCharacterElement().getStartOffset()getCharacterElement().getEndOffset()

最后,这里有一个示例向您展示如何使用这些:

package test;

import java.awt.BorderLayout;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

public class Test {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {

                String text = "<p><mt>Évangile selon Matthieu</mt>\n"
                        + "<c><cn>1</cn>\n"
                        + "<mt>Naissance et enfance de Jésus</mt><s>La généalogie de Jésus</s><r>(<ref v=\"LUK3.23-38\">Lc 3.23-38</ref>)</r><v><vn>1</vn>Voici la généalogie de Jésus-Christ, de la descendance de <g v=\"David\">David</g> et d'<g v=\"Abraham\">Abraham</g>. </v>"
                        + "<p/><v><q><vn>2 </vn>Abraham eut pour descendant <g v=\"Isaac\">Isaac</g>.<br/>Isaac eut pour descendant <g v=\"Jacob\">Jacob</g>.<br/>Jacob eut pour descendant <g v=\"Juda\">Juda</g> et ses frères.</q></v>"
                        + "<v><q><vn>3 </vn>De Thamar, Juda eut pour descendant Péretz et Zérah.<br/>Péretz eut pour descendant Hetsrom.<br/>Hetsrom eut pour descendant Aram.</q></v>"
                        + "<v><q><vn>4 </vn>Aram eut pour descendant Aminadab.<br/>Aminadab eut pour descendant Nahchôn,<br/>Nahchôn eut pour descendant Salma.</q></v>"
                        + "<v><q><vn>5 </vn>De Rahab, Salma eut pour descendant Booz.<br/>De Ruth, Booz eut pour descendant Obed.</q></v></c></p>";

                final JFrame mainFrame = new JFrame("test");
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                final JTextPane field = new JTextPane();
                field.setContentType("text/html");

                HTMLEditorKit kit = (HTMLEditorKit) field.getEditorKit();
                HTMLDocument doc = (HTMLDocument) field.getDocument();

                try (StringReader r = new StringReader(text)) {
                    kit.read(r, field.getDocument(), 0);
                } catch (IOException | BadLocationException ex) {
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                }

                field.setCaretPosition(10);
                field.setSelectionStart(doc.getCharacterElement(field.getCaretPosition()).getParentElement().getStartOffset());
                field.setSelectionEnd(doc.getCharacterElement(field.getCaretPosition()).getParentElement().getEndOffset());

                try (StringWriter w = new StringWriter()) {
                    kit.write(w, field.getDocument(), field.getSelectionStart(), field.getSelectionEnd()-field.getSelectionStart());
                    System.out.println(w.toString());
                } catch (IOException | BadLocationException ex) {
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                }

                mainFrame.getContentPane().setLayout(new BorderLayout());
                mainFrame.getContentPane().add(field,BorderLayout.CENTER);
                mainFrame.setSize(500,500);
                mainFrame.setVisible(true);
            }
        });
    }
}

然后,您还有一些问题需要解决,例如 JTextPane 无法正确表示非 html 标记,因此您必须修复 ViewFactory 以创建您自己的 XMLViewFactory,但这是另一个主题。