【问题标题】:Handling hyperlink right clicks on a JTextPane处理 JTextPane 上的超链接右键单击
【发布时间】:2012-10-17 10:18:16
【问题描述】:

我正在尝试在我的程序中检测对 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);
        }
    }
}

【问题讨论】:

  • 请学习java命名约定并遵守它们。

标签: java swing applet


【解决方案1】:

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

}

【讨论】:

  • 您好,我认为您的解决方案很棒! Tyvm -罗兰
【解决方案2】:

添加通常的MouseListener 并右键单击。单击时使用JEditorPaneviewToModel() 方法在文档中获取偏移量。然后检查是否使用StyledDocumentgetCharacterElement() 方法获取叶子元素。然后检查叶子是否是超链接。

或者你可以使用这个http://java-sl.com/tip_links_in_editable.html来实现你自己的LinkController

【讨论】:

    【解决方案3】:

    基于@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);
        }
    }
    

    此示例还显示了在默认浏览器中打开超链接,并将超链接地址复制到剪贴板。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多