5

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();
      }
    });
  }
}
General Grievance
  • 4,555
  • 31
  • 31
  • 45
peskal
  • 1,213
  • 1
  • 12
  • 28

0 Answers0