我正在尝试检测程序中JTextPane中超链接的右键单击。这个问题在网上确实没什么。有人能帮助我吗?
public class rchltest extends Applet {
public void init() {
JPanel panel = new JPanel(false);
JEditorPane gentextp = new JTextPane();
JScrollPane scrollPane = new JScrollPane(gentextp);
panel.add(scrollPane);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
gentextp.setContentType("text/html");
gentextp.setEditable(false);
gentextp.addHyperlinkListener(new texthll());
gentextp.setPreferredSize( new Dimension( 500, 400 ) );
gentextp.setText("Here is a <a href='http://A'>hyperlink</a>");
this.add( panel );
}
}
class texthll implements HyperlinkListener {
public void hyperlinkUpdate(HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
JEditorPane pane = (JEditorPane)event.getSource();
URL url = event.getURL();
// Show the new page in the editor pane.
JOptionPane.showMessageDialog( null, url);
}
}
}
答案 0 :(得分:8)
使用传统的鼠标监听器。 HyperlinkListener仅转发鼠标移动和左键单击。
这是一个小型演示代码:
import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
public class TestHyperlinks {
private final class HyperlinkMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3) {
Element h = getHyperlinkElement(e);
if (h != null) {
Object attribute = h.getAttributes().getAttribute(HTML.Tag.A);
if (attribute instanceof AttributeSet) {
AttributeSet set = (AttributeSet) attribute;
String href = (String) set.getAttribute(HTML.Attribute.HREF);
if (href != null) {
try {
Desktop.getDesktop().browse(new URI(href));
} catch (IOException e1) {
e1.printStackTrace();
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
}
}
}
}
}
private Element getHyperlinkElement(MouseEvent event) {
JEditorPane editor = (JEditorPane) event.getSource();
int pos = editor.getUI().viewToModel(editor, event.getPoint());
if (pos >= 0 && editor.getDocument() instanceof HTMLDocument) {
HTMLDocument hdoc = (HTMLDocument) editor.getDocument();
Element elem = hdoc.getCharacterElement(pos);
if (elem.getAttributes().getAttribute(HTML.Tag.A) != null) {
return elem;
}
}
return null;
}
}
protected void initUI() {
JPanel panel = new JPanel(false);
JEditorPane gentextp = new JTextPane();
JScrollPane scrollPane = new JScrollPane(gentextp);
panel.add(scrollPane);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
gentextp.setContentType("text/html");
gentextp.setEditable(false);
gentextp.setPreferredSize(new Dimension(500, 400));
gentextp.addMouseListener(new HyperlinkMouseListener());
gentextp.setText("Some text containing an hyperlink: <a href=\"http://www.stackoverflow.com\">a link to stackoverflow</a> and some more text not in an hyperlink");
JFrame f = new JFrame(TestHyperlinks.class.getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel, BorderLayout.CENTER);
f.pack();
f.setSize(f.getWidth() + 100, f.getHeight() + 100);
f.setVisible(true);
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestHyperlinks().initUI();
}
});
}
}
答案 1 :(得分:3)
添加常规MouseListener
并听取右键单击。点击使用viewToModel()
的{{1}}方法获取文档中的偏移量。然后检查是否使用JEditorPane
getCharacterElement()
方法获取叶元素。然后检查叶子是否是超链接。
或者您可以使用此http://java-sl.com/tip_links_in_editable.html来实现自己的StyledDocument
答案 2 :(得分:0)
基于@GuillaumePolet的代码的单个类(HyperTextPane
):
package stackoverflow;
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class Main {
static void showUI() {
javax.swing.SwingUtilities.invokeLater(
() -> {
JFrame frame = new JFrame();
HyperTextPane label = new HyperTextPane("<html>Visit new: <a href=\"http://www.google.pl\">google</a><br>" +
"Visit <a href=\"http://stackoverflow.com\">stackoverflow</a>" +
"</html>");
label.setHyperlinkClickListener(
(e,href,button) -> {
if (button == MouseEvent.BUTTON1) {
HyperTextPane.openHyperlink(href);
} else if (button == MouseEvent.BUTTON3) {
label.showHyperlinkCopyMenu(e,href);
}
});
frame.add(label);
frame.setSize(800,600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
);
}
public static void main(String[] args) {
showUI();
}
}
class HyperTextPane extends JTextPane {
HyperlinkClickListener hyperlinkClickListener;
public HyperTextPane(String htmlText) {
setContentType("text/html");
setEditable(false);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Element h = getHyperlinkElement(e);
if (h != null) {
Object attribute = h.getAttributes().getAttribute(HTML.Tag.A);
if (attribute instanceof AttributeSet) {
AttributeSet set = (AttributeSet) attribute;
String href = (String) set.getAttribute(HTML.Attribute.HREF);
if (href != null) {
hyperlinkClickListener.onHyperlinkClicked(h, href, e.getButton());
}
}
}
}
});
setText(htmlText);
}
public void setHyperlinkClickListener(HyperlinkClickListener hyperlinkClickListener) {
this.hyperlinkClickListener = hyperlinkClickListener;
}
private Element getHyperlinkElement(MouseEvent event) {
JEditorPane editor = (JEditorPane) event.getSource();
int pos = editor.getUI().viewToModel(editor, event.getPoint());
if (pos >= 0 && editor.getDocument() instanceof HTMLDocument) {
HTMLDocument hdoc = (HTMLDocument) editor.getDocument();
Element elem = hdoc.getCharacterElement(pos);
if (elem.getAttributes().getAttribute(HTML.Tag.A) != null) {
return elem;
}
}
return null;
}
public static boolean openHyperlink(String href) {
try {
Desktop.getDesktop().browse(new URI(href));
return true;
} catch (IOException | URISyntaxException e1) {
e1.printStackTrace();
}
return false;
}
public void showHyperlinkCopyMenu(Element elem, String href) {
JPopupMenu popup = new JPopupMenu();
popup.add("Copy URL");
((JMenuItem)popup.getComponent(0)).addActionListener(e -> {
StringSelection selection = new StringSelection(href);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection); }
);
try {
Rectangle rec = modelToView(elem.getStartOffset());
popup.show(this, rec.x, rec.y+rec.height);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public interface HyperlinkClickListener {
void onHyperlinkClicked(Element element, String href, int mouseButton);
}
}
此示例还显示了在默认浏览器中打开超链接,并将超链接地址复制到剪贴板。