gpt4 book ai didi

java - 如何使 TreeSelectionListener 作为 JEditorPane 上的 Hyperlinklistener 工作?

转载 作者:行者123 更新时间:2023-12-01 22:21:29 24 4
gpt4 key购买 nike

我正在开发一个帮助窗口,在该窗口中我使用 jsoup 将 HTML 文件解析到 JSplitPane 右侧的 JEditorPane。 HTML 文件有一个内容页面,我成功地使用 HyperlinkListener 来运行它。 JSplitPane 的右侧是一个 JTree,我在其中进一步从 HTML 中提取了所有链接标签。我开始编写 TreeListener,但我不知道如何在 TreeListener 内的 JEditorPane 上触发 HyperlinkEvent。我有一个 map (linkMap),其中填充了链接的格式化文本值(显示为字符串)作为键,并使用包含链接作为值的 Jsoup 元素。如何触发 HyperlinkEvent,然后在单击 TreeNode 时跳转到 JEditorPane 右侧的页面?

这是我的测试项目中的整个且唯一的类(class)。如果您使用任何包含超链接的本地 html 路径初始化 String url,您将看到树将显示它们,右侧的 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);
}
}


我尝试使用 Jsoup 方法使用 editorPane.setPage() 方法从链接元素获取 a href 标记。这会触发

MalformedURLException: no protocol: #_Toc513013684

(#_Toc513013684 是 a href 标记中的值)。

我也准备好接受我完全以错误的方式做这件事,所以如果您有不同的方式来实现我的目标,请随时留下您的建议!

最佳答案

我自己刚刚找到了答案。我想得太远了,注意到 TreeListener 和 HyperlinkListener 不应该互相调用。我注意到引发“MalformedURLException”的“a href”标记中的值是实际网址的一部分,它只是缺少第一部分,即实际文件路径。所以我所要做的就是将 href 标签与我的 url 字符串连接起来,并将其用作 JEditorPane.setPage() 的参数。为了最终完成这个问题,这里是我的 TreeSelectionListener 的代码:


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))
{
String href = entry.getValue().attr("href");

String link = url.concat(href);

try
{
editorPane.setPage(link);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
});
}

关于java - 如何使 TreeSelectionListener 作为 JEditorPane 上的 Hyperlinklistener 工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58586776/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com