JEditorPane editorPane;
editorPane.addHyperlinkListener(...)
如果editorPane
设置为setEditable(true)
,将不被触发。
因此,我尝试使用editable
动态修改FocusListener
属性:
public void createGui() {
SwingUtilities.invokeLater(() -> {
JEditorPane editorPane = new JEditorPane();
editorPane.setContentType("text/html");
editorPane.setText("<a href='http://google.com'>click me!</a>");
editorPane.setEditable(false);
editorPane.addFocusListener(new FocusListener() {
@Override public void focusGained(FocusEvent e) {
editorPane.setEditable(true); // <-- EDITABLE WHILE FOCUSSED
}
@Override public void focusLost(FocusEvent e) {
editorPane.setEditable(false); // <-- NON-EDITABLE WHILE NON-FOCUSSED
}
});
editorPane.addHyperlinkListener(new HyperlinkListener() {
@Override public void hyperlinkUpdate(HyperlinkEvent e) {
System.out.println(e.getEventType().toString());
}
});
JButton someOtherSwingElement = new JButton("click me to remove focus from editorPane");
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jp = new JPanel(new GridLayout());
jp.add(editorPane);
jp.add(someOtherSwingElement);
jf.add(jp);
jf.pack();
jf.setVisible(true);
}
}
但似乎focusGained()
的内容总是在 hyperlinkUpdate
之前执行,无论前者需要多长时间。为什么呢?
有什么方法可以解决这个问题?
答案 0 :(得分:1)
来自editable JEditorPane hypelinks
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLEditorKit;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.IOException;
public class URLEditorPane {
public static String HTML="<html>\n" +
"<body>\n" +
"Click on the link in the editale JEditorPane <br>\n" +
// "<a href=\"http://java.sun.com\">\nlink</a>" +
"<a href=\"file:///c:/temp/test.html\">\nlink</a>" +
"</body>\n" +
"</html>";
boolean isNeedCursorChange=true;
JTextPane edit=new JTextPane() {
public void setCursor(Cursor cursor) {
if (isNeedCursorChange) {
super.setCursor(cursor);
}
}
};
public URLEditorPane() {
JFrame frame=new JFrame("Click on Links in editable JEditorPane");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(edit);
MyHTMLEditorKit kit=new MyHTMLEditorKit();
// HTMLEditorKit kit=new HTMLEditorKit();
edit.setEditorKit(kit);
// edit.setEditable(false);
edit.setText(HTML);
edit.addHyperlinkListener(new HTMLListener());
frame.setSize(500,300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
new URLEditorPane();
}
private class HTMLListener implements HyperlinkListener {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
try {
edit.setPage(e.getURL());
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
public class MyHTMLEditorKit extends HTMLEditorKit {
MyLinkController handler=new MyLinkController();
public void install(JEditorPane c) {
MouseListener[] oldMouseListeners=c.getMouseListeners();
MouseMotionListener[] oldMouseMotionListeners=c.getMouseMotionListeners();
super.install(c);
//the following code removes link handler added by original
//HTMLEditorKit
for (MouseListener l: c.getMouseListeners()) {
c.removeMouseListener(l);
}
for (MouseListener l: oldMouseListeners) {
c.addMouseListener(l);
}
for (MouseMotionListener l: c.getMouseMotionListeners()) {
c.removeMouseMotionListener(l);
}
for (MouseMotionListener l: oldMouseMotionListeners) {
c.addMouseMotionListener(l);
}
//add out link handler instead of removed one
c.addMouseListener(handler);
c.addMouseMotionListener(handler);
}
public class MyLinkController extends LinkController {
public void mouseClicked(MouseEvent e) {
JEditorPane editor = (JEditorPane) e.getSource();
if (editor.isEditable() && SwingUtilities.isLeftMouseButton(e)) {
if (e.getClickCount()==2) {
editor.setEditable(false);
super.mouseClicked(e);
editor.setEditable(true);
}
}
}
public void mouseMoved(MouseEvent e) {
JEditorPane editor = (JEditorPane) e.getSource();
if (editor.isEditable()) {
isNeedCursorChange=false;
editor.setEditable(false);
isNeedCursorChange=true;
super.mouseMoved(e);
isNeedCursorChange=false;
editor.setEditable(true);
isNeedCursorChange=true;
}
}
}
}
}
答案 1 :(得分:0)
HyperlinkListener
似乎依赖于FocusListener
,因此无法绕过setEditable(false)
条件。
最笨拙但最简单的解决方法可能是将editorPane.setEditable(true);
置于其自己的线程中并在其前面进行睡眠,因此HyperlinkListener
有足够的时间来触发其HyperlinkUpdate
方法。我发现即使100毫秒仍然不够,所以我把它设置为250毫秒。这意味着,点击editorPane
后,您将无法修改其内容250毫秒。这不是一个好的编程风格,但完全可用且易于理解。代码示例:
editorPane.addFocusListener(new FocusListener() {
@Override public void focusGained(FocusEvent e) {
new Thread(() -> {
try {
Thread.sleep(250);
} catch (InterruptedException e1) {}
editorPane.setEditable(true);
}).start();
}
@Override public void focusLost(FocusEvent e) {
editorPane.setEditable(false);
}
});
Here是Stanislav Lapitsky的另一种方法。不过,它说的是
我们所需要的只是调用setEditable(false)并调用super方法然后恢复可编辑状态。
,所以即使这不是真正的“解决方案”,而是一种解决方法
我很高兴听到别人对此的看法。