Search code examples
javaswinguser-interfacetooltipcustom-component

Extending Swing's ToolTipManager to change behaviour on hover?


I'd like to implement a ToolTip in Swing that has customised behaviour: the longer the user hovers over the component, the more detail should be shown in the tooltip (i.e., a few new lines are added after a few seconds of the user hovering over the component). I just need to check whether this is really doable with Swing without things getting too messy. My idea at the moment would probably be:

  • Extend ToolTipManager
  • Override mouseEntered to start a timer (maybe use javax.swing.Timer?). Call setToolTipText and createToolTip to refresh the tooltip and add new information at regular intervals
  • Override mouseExited to reset the timer
  • Probably use setDismissDelay to set the dismiss delay to something a lot longer (or Integer.MAX_VALUE)

Is such a thing feasible or is this not a good way to work with Swing (sorry, I'm pretty new to it)? Is there a better way of doing this?

[edit] Hmm, just remembered that ToolTipManager is a singleton with a constructor that only has package visibility, so it can't be extended.

[edit 2] I'm trying out a few solutions at the moment. One thing that I forgot to add is that I do need to know which component is being hovered over - which I guess means I'll need to be working with some sort of listener with a mouseEntered() method (or be able to access this information). And no other interactivity with the popup/tooltip is needed - it just needs to display information.


Solution

  • (This may seem a bit confusing so let me know if you need me to clarify let me know and I'll try to show you how I picture the code) I think your idea might work like if you extend it, and also make a private class that extends Threadand then in the run() method you do something like

    while(true)
    {
        sleep(1);
        timeElapsed++;
    }
    

    And in your class that extends ToolTipManager, create a field for that class that extends Thread and in the mouseEntered(MouseEvent e) instantiate the thing like:

    extendsThreadClass = new ExtendsThreadClass();
    extendsThreadClass.start();
    

    and then in the mouseExited(MouseEvent e) method do

    extendsThreadClass = null;

    Then in that mouseEntered(MouseEvent e) method after starting the Thread then you can do what you want to do after the time thing like

    if(timeElapsed > 3000)
    {
       //what you want to do here
    }
    

    Sorry it may be confusing, let me know if i can clear it up for you