问题
I've got a problem: I want to use internal anchors <a name="x">
and links <a href="#x">
inside a JEditorPane.
The content of the pane is not loaded from a resource but dynamically created and available as a String.
How can I get my JEditorPane to scroll to the proper location? (in the example it should scroll to the top) The listener only catches null, which adds to the problem.
Here's my SSCCCE:
public static void main(final String[] args) {
final JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.setTitle("JEditorPane Test");
final String text = "<html><body><a name='link1'>test</a>some text<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />some more text<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />some more text<a href='#link1'>jump to top</a></body></html>";
final JEditorPane ep = new JEditorPane();
ep.setContentType("text/html");
ep.setText(text);
ep.setEditable(false);
ep.addHyperlinkListener(new HyperlinkListener() {
@Override public void hyperlinkUpdate(final HyperlinkEvent pE) {
if (HyperlinkEvent.EventType.ACTIVATED == pE.getEventType())
System.out.println("ep link click: " + pE.getURL());
}
});
final JScrollPane sp = new JScrollPane(ep);
f.add(sp);
f.setBounds(200, 200, 400, 400);
f.setVisible(true);
}
回答1:
Okay I finally got this solved.
I had been testing around with scrollToReference()
, but it somehow didn't work.
Then I played with HTML parsing and anchors and carets and setCaretPosition()
which worked only sometimes.
Then out of pure coincidence I had included scrollToReference()
again in my code and scrolling suddenly worked... and still works flawlessly!
Here's the working code:
public static void main(final String[] args) {
final JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.setTitle("JEditorPane Test");
final String text = "<html><body><a name='link1'>test</a>some text<br /><a href='#thisisbottom'>down</a><br /><br /><br /><br /><br /><br /><br /><br /><br /><a name='mid1'></a>some more text<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />some more text [<a href='#link1'>jump to top</a>] <br /> or jump to <a name='thisisbottom' href='#mid1'>center</a></body></html>";
final JEditorPane ep = new JEditorPane();
ep.setContentType("text/html");
ep.setText(text);
ep.setEditable(false);
ep.addHyperlinkListener(new HyperlinkListener() {
@Override public void hyperlinkUpdate(final HyperlinkEvent pE) {
if (HyperlinkEvent.EventType.ACTIVATED == pE.getEventType()) {
System.out.println("JEditorPane link click: url='" + pE.getURL() + "' description='" + pE.getDescription() + "'");
String reference = pE.getDescription();
if (reference != null && reference.startsWith("#")) { // link must start with # to be internal reference
reference = reference.substring(1);
ep.scrollToReference(reference);
}
}
}
});
final JScrollPane sp = new JScrollPane(ep);
f.add(sp);
f.setBounds(200, 200, 400, 400);
f.setVisible(true);
}
回答2:
You can do that this way:
import java.awt.Point;
import java.util.logging.Logger;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
public class PaneWithScroll {
private static final String TEXT =
"<html>"
+ "<head>"
+ "</head>"
+ "<body>"
+ "<p><a href=\"#top\">Go top</a></p>"
+ "</body>"
+ "</html>";
private static final String TOP = "#top";
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new PaneWithScrollFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
private static class PaneWithScrollFrame extends JFrame {
private PaneWithScrollFrame() {
super.setName("Pane With Scroll");
this.addComponents();
super.setSize(640, 480);
}
private void addComponents() {
JEditorPane editorPane = new JEditorPane();
editorPane.setContentType("text/html");
editorPane.setEditable(false);
editorPane.setText(TEXT);
final JScrollPane scrollpane = new JScrollPane(editorPane);
editorPane.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) {
String description = e.getDescription();
if (TOP.equals(description)) {
JViewport viewport = scrollpane.getViewport();
viewport.setViewPosition(new Point(0, 0));
}
}
}
});
super.add(scrollpane);
}
}
}
来源:https://stackoverflow.com/questions/14054601/jumping-to-internal-anchors-in-jeditorpane