调用 JEditor.setEditable() 时更改悬停在超链接上的光标

发布于 2024-11-25 21:45:39 字数 3040 浏览 0 评论 0原文

我有一个包含超链接的 JTextPane。当它可编辑时,超链接不可单击,并且光标悬停在其上时不会改变状态(例如,悬停在手上)。当它不可编辑时,超链接可点击,并且光标在悬停在其上时确实改变状态。完美的。

问题是,如果在 JTextPane 的可编辑性更改时光标已经悬停在 JTextPane 上,则光标不会更新。 (据我所知)光标更新的唯一方法是移动它。

即使光标可能不会更改状态,当按下鼠标且 JTextPane 不可编辑时,HyperlinkListener 也会看到 ACTIVATED 事件。有没有办法强制光标重新评估它应该处于的状态,并在我更改其下方面板的状态时自行更新?

基本上,我希望光标图标始终对应于按下鼠标时会发生的情况。是的,这是一个边界情况,但它仍然很烦人。

这是一些可以使用的示例代码。

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;

/**
 * Every five seconds the editability of the JTextPane is changed. If the
 * editability changes to false when the mouse is hovering over the hyperlink,
 * the cursor will not change to a hand until it is moved off and then back
 * onto the hyperlink. If the editability changes to true when the mouse is
 * hovering over the hyperlink, the cursor will not change back to normal
 * until it is moved slightly.
 * 
 * I want the cursor to update without having to move the mouse when it's
 * already hovering over a hyperlink.
 */
@SuppressWarnings("serial")
public class HyperlinkCursorProblem extends JFrame {

  public HyperlinkCursorProblem(String title) {
    super(title);

    Container pane = getContentPane();
    pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));

    final JLabel editabilityLabel = new JLabel("Editable");
    pane.add(editabilityLabel);

    final JTextPane textPane = new JTextPane();
    textPane.setContentType("text/html");

    StringBuilder text = new StringBuilder();
    text.append("<html><body>");
    text.append("<a href=\"http://www.example.com/\">");
    text.append("Click here for fun examples.");
    text.append("</a>");
    text.append("</body></html>");
    textPane.setText(text.toString());
    textPane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent e) {
        if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          System.out.println("Going to " + e.getURL());
        }
      }
    });
    textPane.setPreferredSize(new Dimension(500, 250));
    pane.add(textPane);

    new Thread(new Runnable() {
      public void run() {
        while (true) {
          try {
            Thread.sleep(5000);

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    boolean editable = !textPane.isEditable();
                    textPane.setEditable(editable);
                    editabilityLabel.setText(editable ? "Editable" : "Not Editable");
                }
            });
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JFrame frame = new HyperlinkCursorProblem("Large File Mover");

        // Display the window.
        frame.setVisible(true);
        frame.pack();
      }
    });
  }
}

I have a JTextPane containing hyperlinks. When it's editable, hyperlinks aren't clickable, and the cursor does not change state when hovering over them (e.g. to a hand). When it is not editable, hyperlinks are clickable, and the cursor does change state when hovering over them. Perfect.

Here's the problem, if the cursor is already hovering over a JTextPane when its editability is changed, the cursor does not update. The only way (that I know of) for the cursor to update is to move it around.

Even though the cursor may not change state, the HyperlinkListeners will see an ACTIVATED event when the mouse is pressed and the JTextPane is not editable. Is there a way force the cursor reevaluate what state it should be in and update itself when I change the state of the panel beneath it?

Basically, I want the cursor icon to always correspond to what will happen when the mouse is pressed. Yes, this is a boundary case, but it's still pretty annoying.

Here is some sample code to play with.

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;

/**
 * Every five seconds the editability of the JTextPane is changed. If the
 * editability changes to false when the mouse is hovering over the hyperlink,
 * the cursor will not change to a hand until it is moved off and then back
 * onto the hyperlink. If the editability changes to true when the mouse is
 * hovering over the hyperlink, the cursor will not change back to normal
 * until it is moved slightly.
 * 
 * I want the cursor to update without having to move the mouse when it's
 * already hovering over a hyperlink.
 */
@SuppressWarnings("serial")
public class HyperlinkCursorProblem extends JFrame {

  public HyperlinkCursorProblem(String title) {
    super(title);

    Container pane = getContentPane();
    pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));

    final JLabel editabilityLabel = new JLabel("Editable");
    pane.add(editabilityLabel);

    final JTextPane textPane = new JTextPane();
    textPane.setContentType("text/html");

    StringBuilder text = new StringBuilder();
    text.append("<html><body>");
    text.append("<a href=\"http://www.example.com/\">");
    text.append("Click here for fun examples.");
    text.append("</a>");
    text.append("</body></html>");
    textPane.setText(text.toString());
    textPane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent e) {
        if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          System.out.println("Going to " + e.getURL());
        }
      }
    });
    textPane.setPreferredSize(new Dimension(500, 250));
    pane.add(textPane);

    new Thread(new Runnable() {
      public void run() {
        while (true) {
          try {
            Thread.sleep(5000);

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    boolean editable = !textPane.isEditable();
                    textPane.setEditable(editable);
                    editabilityLabel.setText(editable ? "Editable" : "Not Editable");
                }
            });
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JFrame frame = new HyperlinkCursorProblem("Large File Mover");

        // Display the window.
        frame.setVisible(true);
        frame.pack();
      }
    });
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文