Java 处理JTextPane上的超链接右键单击

Java 处理JTextPane上的超链接右键单击,java,swing,applet,Java,Swing,Applet,我试图在程序的JTextPane中检测对超链接的右键单击。网上真的没有这个问题。有人能帮我吗 public class rchltest extends Applet { public void init() { JPanel panel = new JPanel(false); JEditorPane gentextp = new JTextPane(); JScrollPane scrollPane = new JScrollPa

我试图在程序的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);
        }
    }
}
公共类rchltest扩展小程序{
公共void init(){
JPanel面板=新JPanel(假);
JEditorPane gentextp=新的JTextPane();
JScrollPane scrollPane=新的JScrollPane(gentextp);
panel.add(滚动窗格);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL\u SCROLLBAR\u ALWAYS);
setContentType(“text/html”);
gentextp.setEditable(false);
gentextp.addHyperlinkListener(新的texthll());
gentextp.setPreferredSize(新维度(500400));
setText(“这是一个”);
本条添加(面板);
}
}
类texthll实现HyperlinkListener{
公共无效hyperlinkUpdate(HyperlinkEvent事件){
if(event.getEventType()==HyperlinkEvent.EventType.ACTIVATED){
JEditorPane=(JEditorPane)event.getSource();
URL=event.getURL();
//在编辑器窗格中显示新页面。
showMessageDialog(null,url);
}
}
}

添加常用的
鼠标侦听器
,然后右键单击收听。单击使用
JEditorPane
viewToModel()
方法获取文档中的偏移量。然后检查是否使用
StyledDocument
getCharacterElement()
方法获取叶元素。然后检查叶是否为超链接


或者您可以使用它来实现自己的
LinkController

使用传统的鼠标侦听器。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();
            }
        });
    }

}
导入java.awt.BorderLayout;
导入java.awt.Desktop;
导入java.awt.Dimension;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.io.IOException;
导入java.net.URI;
导入java.net.URISyntaxException;
导入javax.swing.JEditorPane;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JTextPane;
导入javax.swing.SwingUtilities;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.event.HyperlinkEvent;
导入javax.swing.event.HyperlinkListener;
导入javax.swing.text.AttributeSet;
导入javax.swing.text.Element;
导入javax.swing.text.html.html;
导入javax.swing.text.html.HTMLDocument;
公共类测试超链接{
私有最终类HyperlinkMouseListener扩展了MouseAdapter{
@凌驾
公共无效mouseClicked(MouseEvent e){
如果(例如getButton()==MouseEvent.BUTTON3){
元素h=getHyperlinkElement(e);
如果(h!=null){
Object attribute=h.getAttributes().getAttribute(HTML.Tag.A);
if(属性集合的属性实例){
属性集=(属性集)属性;
String href=(String)set.getAttribute(HTML.Attribute.href);
如果(href!=null){
试一试{
getDesktop().browse(新URI(href));
}捕获(IOE1异常){
e1.printStackTrace();
}捕获(URISyntaxException e1){
e1.printStackTrace();
}
}
}
}
}
}
私有元素getHyperlinkElement(MouseeEvent事件){
JEditorPane编辑器=(JEditorPane)event.getSource();
int pos=editor.getUI().viewToModel(editor,event.getPoint());
如果(pos>=0&&editor.getDocument()实例为HTMLDocument){
HTMLDocument hdoc=(HTMLDocument)editor.getDocument();
Element elem=hdoc.getCharacterElement(位置);
if(elem.getAttributes().getAttribute(HTML.Tag.A)!=null){
返回元素;
}
}
返回null;
}
}
受保护的void initUI(){
JPanel面板=新JPanel(假);
JEditorPane gentextp=新的JTextPane();
JScrollPane scrollPane=新的JScrollPane(gentextp);
panel.add(滚动窗格);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL\u SCROLLBAR\u ALWAYS);
setContentType(“text/html”);
gentextp.setEditable(false);
gentextp.setPreferredSize(新维度(500400));
gentextp.addMouseListener(新的HyperlinkMouseListener());
setText(“包含超链接的一些文本:以及不在超链接中的更多文本”);
JFrame f=newjframe(TestHyperlinks.class.getSimpleName());
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f、 添加(面板、边框布局、中心);
f、 包装();
f、 设置大小(f.getWidth()+100,f.getHeight()+100);
f、 setVisible(真);
}
publicstaticvoidmain(字符串[]args)抛出ClassNotFoundException、InstantiationException、IllegalAccessException、,
不受支持的LookandFeelException{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
新建TestHyperlinks().initUI();
}
});
}
}
基于@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);
    }
}
包堆栈溢出;
导入javax.swing.*;
导入javax.swing.text.AttributeSet;
导入javax.swing.text.BadLocationException;
导入javax.swing.text.Element;
导入javax.swing.text.html.html;
导入javax.swing.text.html.HTMLDocument;
导入java.awt.*;
导入java.awt.datatransfer.Clipboard;
导入java.awt.datatransfer.StringSelecti