Я работаю над окном справки, в котором я анализировал HTML-файл с помощью jsoup на панели JEditorPane справа от JSplitPane. В файле HTML есть страница с содержимым, которую я успешно использовал для работы с HyperlinkListener. Правая часть JSplitPane - это JTree, где я дополнительно извлек все теги ссылок из HTML. Я начал писать TreeListener, но я не могу понять, как вызвать HyperlinkEvent на JEditorPane внутри TreeListener. У меня есть карта (linkMap), заполненная отформатированной text value
ссылкой (отображаемое значение в виде строки) в качестве ключа и элемента Jsoup, который содержит ссылку в качестве значения. Как запустить HyperlinkEvent, а затем перейти на страницу с правой стороны в JEditorPane, щелкнув TreeNode?
Это полный и единственный класс в моем тестовом проекте. Если вы инициализируете String url с любым локальным html-путем, который содержит гиперссылки, вы увидите, что дерево отобразит их, а JEditorPane справа сделает их кликабельными и уже правильно внедрил HyperlinkListener. Я хочу, чтобы дерево работало так же, как и гиперссылки в EditorPane.
package yur.html;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.BoxLayout;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class HTMLDisplayer
{
private String url = ""; // local html-file path
private JFrame frame;
private JSplitPane splitPane;
private JPanel leftPanel;
private JScrollPane leftScrollPane;
private JScrollPane rightScrollPane;
private JEditorPane editorPane;
private JTree tree;
private JLabel descriptionLabel;
private DefaultMutableTreeNode root;
private DefaultMutableTreeNode lastChapterNode;
private Map<String, Element> linkMap;
public HTMLDisplayer()
{
initGui();
}
private HyperlinkListener helpContentsHyperlinkListener = new HyperlinkListener()
{
@Override
public void hyperlinkUpdate(HyperlinkEvent ev)
{
if(ev.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
{
JEditorPane pane = (JEditorPane) ev.getSource();
if(ev instanceof HTMLFrameHyperlinkEvent)
{
HTMLFrameHyperlinkEvent event = (HTMLFrameHyperlinkEvent) ev;
HTMLDocument doc = (HTMLDocument) pane.getDocument();
doc.processHTMLFrameHyperlinkEvent(event);
}
else
{
try
{
pane.setPage(ev.getURL());
}
catch(Throwable t)
{
t.printStackTrace();
}
}
}
}
};
public HyperlinkListener getHelpContentsHyperlinkListener()
{
return helpContentsHyperlinkListener;
}
public void setHelpContentsHyperlinkListener(HyperlinkListener helpContentsHyperlinkListener)
{
this.helpContentsHyperlinkListener = helpContentsHyperlinkListener;
}
public static void main(String[] args) throws Exception
{
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
catch(Exception e)
{
e.printStackTrace();
}
HTMLDisplayer htmlDisplayer = new HTMLDisplayer();
htmlDisplayer.setVisible();
}
private void initGui()
{
initRightPane();
initLeftPane();
initSplitPane();
initFrame();
}
private void initRightPane()
{
try
{
editorPane = new JEditorPane(url);
}
catch(IOException e)
{
e.printStackTrace();
}
editorPane.addHyperlinkListener(getHelpContentsHyperlinkListener());
editorPane.setEditable(false);
editorPane.setFocusable(false);
rightScrollPane = new JScrollPane(editorPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
private void initLeftPane()
{
descriptionLabel = new JLabel("Hilfe");
descriptionLabel.setBorder(new EmptyBorder(5, 0, 5, 0));
leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
initTree();
leftScrollPane = new JScrollPane(tree, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
leftPanel.add(descriptionLabel);
leftPanel.add(leftScrollPane);
}
private void initTree()
{
Elements links = getContents();
initNodes(links);
tree = new JTree(root);
addTreeSelectionListener(tree);
}
private static Elements getContents()
{
File file = new File("C:\\\\SoftwareEntwicklung\\\\yur.poi\\\\Hilfe_VR_FESAe.htm");
try
{
return parseLinksFromFile(file);
}
catch(IOException e)
{
e.printStackTrace();
}
return null;
}
private static Elements parseLinksFromFile(File file) throws IOException
{
Document doc = Jsoup.parse(file, "windows-1252", "");
Elements links = doc.select("a[href]");
return links;
}
private void initNodes(Elements links)
{
root = new DefaultMutableTreeNode("Inhaltsverzeichnis");
createNodes(links);
}
private void createNodes(Elements links)
{
linkMap = new HashMap<>();
for(Element link : links)
{
createNode(link);
}
}
private void createNode(Element link)
{
String uneditedText = link.text();
String[] splitText = uneditedText.split(" ");
String text = splitText[0];
text = text.replaceAll("[^a-zA-Z0-9äÄöÖüÜ *]+", "");
Pattern pattern = Pattern.compile(".*[0-9]+$");
Matcher matcher = pattern.matcher(text);
text = text.substring(0, text.length() - 2);
boolean isSpace = Character.isWhitespace(text.charAt(text.length() - 1));
if(isSpace)
{
text = text.substring(0, text.length() - 1);
}
linkMap.put(text, link);
if(matcher.matches())
{
if(!text.contains(" "))
{
DefaultMutableTreeNode chapterNode = new DefaultMutableTreeNode(text);
root.add(chapterNode);
lastChapterNode = chapterNode;
}
else
{
DefaultMutableTreeNode node = new DefaultMutableTreeNode(text);
lastChapterNode.add(node);
}
}
}
private void addTreeSelectionListener(JTree tree)
{
tree.addTreeSelectionListener(new TreeSelectionListener()
{
@Override
public void valueChanged(TreeSelectionEvent ev)
{
DefaultMutableTreeNode lastSelectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if(lastSelectedNode == null)
{
return;
}
Object nodeInfo = lastSelectedNode.getUserObject();
for(Map.Entry<String, Element> entry : linkMap.entrySet())
{
if(entry.getKey().equals(nodeInfo))
{
// TODO
System.out.println(entry.getKey());
}
}
}
});
}
private void initSplitPane()
{
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setLeftComponent(leftPanel);
splitPane.setRightComponent(rightScrollPane);
}
private void initFrame()
{
frame = new JFrame("Hilfe");
frame.getContentPane().add(splitPane, BorderLayout.CENTER);
frame.setSize(new Dimension(1450, 1000));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void setVisible()
{
frame.setVisible(true);
}
}
Я пробовал метод editorPane.setPage()
с методами Jsoup, чтобы получить тег a href
из элемента ссылки. Это вызывает
MalformedURLException: нет протокола: # _Toc513013684
(#_ Toc513013684 - это значение в теге href).
I'mтакже готов признать, что я делаю это неправильно, поэтому, если у вас есть другой способ достижения моей цели, пожалуйста, не стесняйтесь оставлять свои предложения!