Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

Tooltips, the mouse wheel and JScrollPane

843807Oct 17 2009 — edited Oct 20 2009
Hi,
I've implemented a JTable which provides a cell-dependent tooltip. The table is displayed within a JScrollPane and I've noticed a bug: if I scroll the pane using the mouse wheel, the tooltip isn't affected, it remains relevant for the cell which was under the cursor before scrolling. When I move the mouse slightly, the tooltip updates properly.
In order to implement cell-dependent tooltips, I've overriden JTable.prepareRenderer, but the same problem appears when using the methods described in the tutorial ([http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#celltooltip]). It appears that ToolTipManager ignores MouseWheelEvent's, which is reasonable for most components... but inappropriate for scrollable tables, lists etc.
I did manage to capture the MouseWheelEvent's by using JScrollPane.addMouseWheelListener with my JTable, but haven't found a way to force proper update of the tooltip. Setting the tooltip text of the table seems to have no effect. Passing the MouseWheelEvent to ToolTipManager.mouseMoved() causes the current (and outdated) tooltip to be hidden, but a new one is not displayed until after the mouse is moved to a different position.
I'd really dislike confusing the ToolTipManager with false mouse locations just for this... Is there a better solution to this problem?
TIA
Babelfish

Comments

darrylburke
To get better help sooner, post a [_SSCCE_|http://mindprod.com/jgloss/sscce.html] that clearly demonstrates your problem.

Use code tags to post codes -- [code]CODE[/code] will display as
CODE
Or click the CODE button and paste your code between the {code} tags that appear.

db
843807
You're right of course, it just didn't occur to me b/c I thought this should be a known issue, which someone might recognize and have a workaround...
It's easy to reproduce the problem in this case, though, using either the second or third example in the section I've linked to above:
- run the example
- reduce the window size so that at least one row isn't visible
- point the mouse to a cell which has a tooltip and wait for the tooltip to appear
- use the mouse wheel to scroll the table
The tooltip won't be updated until the mouse is moved.
camickr
Passing the MouseWheelEvent to ToolTipManager.mouseMoved() causes the current (and outdated) tooltip to be hidden, but a new one is not displayed until after the mouse is moved to a different position.
Try creating a new MouseMoved event and pass that to the mouseMoved() method.
kleopatra-JavaNet
sounds like a bug to me, you might consider to report it and hope for the best ;-)

Rob, diirty trick - but working nicely. Will add to my tool box :-)

Cheers
Jeanette
843807
An SSCCE along with what appears to be a solution (camickr's suggestion). I decided to add an adjusment listener to the scroll bar, since scroll movement can come from both the wheel and the keyboard. This way, both types of movements are caught.
import java.awt.Component;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import java.awt.event.MouseEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.AdjustmentEvent;
import javax.swing.ToolTipManager;

public class TooltipsAndScrollPane {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        TableCellRenderer renderer = new TableCellRenderer() {
            JLabel label = new JLabel();

            public Component getTableCellRendererComponent(
                    JTable table, Object value,
                    boolean isSelected, boolean hasFocus,
                    int row, int column) {
                label.setToolTipText("(" + row+ "," + column + ")");
                return label;
            }

        };

        final JTable table = new JTable(50,50);
        for(int i = 0; i < table.getColumnCount(); i++) {
            table.getColumnModel().getColumn(i).setCellRenderer(renderer);
        }


        JScrollPane scroller = new JScrollPane(table);
        //uncomment for solution
        /*
        scroller.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
            public void adjustmentValueChanged(AdjustmentEvent e) {
              java.awt.Point p = table.getMousePosition();
                if(p != null) {
                    MouseEvent phantom = new MouseEvent(
                            table,MouseEvent.MOUSE_MOVED,
                            System.currentTimeMillis(),0,p.x,p.y,1,false);
                    ToolTipManager.sharedInstance().mouseMoved(phantom);
                }
            }
        });
        */
        
        JFrame frame = new JFrame();
        frame.add(scroller);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300,300);
        frame.setVisible(true);
    }
}
kleopatra-JavaNet
Hi Maxideon,

thanks for the api update - wasn't aware of the getMousePosition, probably should do what I preach and occasionally re-scan the class method outline :-)

As to your approach adding an AdjustmentListener: I think that still doesn't cover all possibilities - incorrect mapping of mouse position to cell coordinates might still happen, f.i. on horizontal resizing the scrollpane's parent. Plus, personally I don't like such a close coupling to a parent's parent child (what's that to the table - an great-aunt, don't know). Actually, triggered by this thread, I noticed that we at SwingX - which supports per-cell rollover in all collection components - have a similar misbehaviour:

[http://forums.java.net/jive/thread.jspa?threadID=68225&tstart=0]

Currently, I have the best (relatively, not quite entirely satisfying in our context) result with a ComponentListener on the table: we get a componentMoved on scrolling and a componentResized on resizing the parent - if parent resizing results in table resizing (which might not be always the case, but don't think that's a problem for tooltips)

CU
Jeanette
843807
I added a timer to my SSCCE so that it would resize the frame at intervals. I also made the JTable smaller so that it would resize when the JScrollPane did. Adjustment events were thrown, and the tooltip was indeed updated, but its text was what it should of been prior to all the resizing. So I guess it just has to deal with the relative order in which things are resized, adjusted, and moved about.

I then tried your ComponentListener approach and it seemed like a complete solution. The tooltip was always updated with the correct text no matter what twisted way I could manipulate the JTable and the JScrollPane. Good call.
843807
Thanks Kleopatra and everyone!
I'm not doing this for work but as a hobby (would you believe!) so I don't have time to check this - or write an SSCCE for that matter - except on weekends. But I suppose it should work for me if it does for other ;)
I did consider reporting this as a bug, but in the tutorials I've found links for feedback (on the tutorials themselves) or for these forums. Anyone know where I could submit it?
Thanks again!
Uriah
kleopatra-JavaNet
The place to report bugs is Sun's Bug Parade

[http://bugs.sun.com/bugdatabase/]

have fun and patience :-)

Cheers
Jeanette
1 - 9
Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Nov 17 2009
Added on Oct 17 2009
9 comments
638 views