跳转到 JEditorPane 中的内部锚点

Posted

技术标签:

【中文标题】跳转到 JEditorPane 中的内部锚点【英文标题】:Jumping to internal anchors in JEditorPane 【发布时间】:2012-12-12 20:07:53 【问题描述】:

我遇到了一个问题:我想在 JEditorPane 中使用内部锚点 <a name="x"> 和链接 <a href="#x">

窗格的内容不是从资源加载的,而是动态创建的,可以作为字符串使用。

如何让我的 JEditorPane 滚动到正确的位置? (在示例中它应该滚动到顶部) 监听器只捕获 null,这增加了问题。

这是我的 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】:

你可以这样做:

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);
    
  

【讨论】:

非常感谢您的意见,它已经帮助了一点。但我一直在寻找更通用的解决方案。感谢您的帖子,我实际上找到了一个,将在下面发布。 不被要求进入顶部,而是进入任何锚链接【参考方案2】:

好的,我终于解决了这个问题。

我一直在用scrollToReference() 进行测试,但不知何故它不起作用。 然后我使用了 HTML 解析、锚点和插入符号以及 setCaretPosition(),它们只在某些时候起作用。 然后出于纯粹的巧合,我再次将scrollToReference() 包含在我的代码中并且滚动突然起作用了......并且仍然可以完美地工作!

这是工作代码:

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);

【讨论】:

哦,是的,这并不明显,但 JEditorPane 控制其周围的 JScrollPane 进行滚动。 顺便说一句,有没有办法将此标记为已解决?除了手动编辑标题? 是的,选择您自己的答案作为已接受(或解决问题的答案),这就是在 *** 中将其标记为已解决的方式。 我这边的快速评论:看起来旧代码由于某种原因不再包含滚动代码。我现在用多个链接和滚动更新了答案。 点击链接后,我遇到了一个问题,即光标没有从手上恢复。添加行setCursor(editorKit.getDefaultCursor()); 修复它。

以上是关于跳转到 JEditorPane 中的内部锚点的主要内容,如果未能解决你的问题,请参考以下文章

什么是锚点

HTML做的网页 如何使当前页面跳转到另一页面锚点处,在线等!!

thinkphp怎么跳转到指定页面的锚点

JS / jQuery 实现页面跳转到指定位置-锚点

js如何实现进入页面后自动跳转到锚点

进入页面跳转到指定锚点