0

I have a mouse listener attached to a vertical jScrollbar. The horizontal aspect of the content is controlled by hover position. Right now, when the user drags the vertical scrollbar handle, the content scrolls vertically just fine, but they can only see the right-most content (horizontally speaking) because the cursor is off the right side of the jPanel.

What I would like to do is, once the user clicks to drag the vertical scrollbar, I want to allow them to hover the cursor over the content (while the mouse button is down) and have the horizontal position of the content updated.

However, even though I have added an over-ridden mouseDragged function to my jscrollbar's mouse listener to update a manually maintained hover position, it is not getting fired. Here's my code:

getSecondaryScrollBar().addMouseListener(new MouseAdapter() {
    ...
    @Override
    public void mouseDragged(final MouseEvent e) {
        debug("Hover pixel position during drag: [" + e.getX() + "]",8);
        if(e.getX() < 0) {
            //Set the hover position to wherever the cursor has wandered to while dragging the secondary scrollbar
            map.setHoverIndex(map.getIndex(scrollPane.getViewport().getSize().width + e.getX()));
        } else {
            //Set the hover position as the far right label
            map.setHoverIndex(-1);
        }
        repaint();
    }
});

The debug message does not print upon drag of the scrollbar. The labels are scrolling vertically. I even debugged by adding a breakpoint, so I know mouseDragged is not even getting called. I also tried the mouseMoved function with the same result.

I have an adjustment listener that takes an adjustment event object that handles the vertical dragging of content, but it does not have access to the mouse event getX() function.

I also have mouseDragged and mouseMoved functions as a part of the main class for when the cursor is over the jPanel. They're used for controlling horizontal position and making selections. Both work splendidly:

@Override
public void mouseMoved(final MouseEvent e) {
    setHoverPosition(e);
    hoverIndex = map.getIndex(getPrimaryHoverPosition(e));
    repaint();
}
@Override
public void mouseDragged(final MouseEvent e) {
    setHoverPosition(e);
    hoverIndex = map.getIndex(getPrimaryHoverPosition(e));
    map.setHoverIndex(hoverIndex);
    debug("Selecting from " + map.getSelectingStart() + " to " + map.getIndex(getPrimaryHoverPosition(e)),8);
    repaint();
}

Finally, here's a screen recording that should clarify what I'm doing in case my description is insufficient:

https://dl.dropboxusercontent.com/u/87939936/StackOverflow/getX_on_scrollbar_drag_question.mov

Does anyone know how to get the cursor position during a drag of the vertical scrollbar?

hepcat72
  • 890
  • 4
  • 22
  • I doubt you can do what you want using a JScrollBar (For a vertical scrollbar, if the mouse strays very far left or right of the scrollbar the scrollbar will pop back to its start position); What you need is a panner that can scroll both directions (up/down and left/right) at the same time. Unfortunately, swing does not have such a control. – FredK Jul 27 '15 at 22:14
  • Actually, I have a very large screen and when I garb the scrollbar and hover to the extreme opposite end of the screen, I can still drag it up and down. Hovering away does not seem to cause it to pop back to its start position, so if that's the only reason you think it's not possible with a jscrollbar, is there another reason it wouldn't be possible? – hepcat72 Jul 28 '15 at 15:11

2 Answers2

1

mouseDragged and mouseMoved (attached to the jscrollbar) are not called during a jscrollbar drag and the AdjustmentEvent object has no way to obtain the cursor position or to get access to an object that can return it either. Therefor you must find the cursor position externally using something like MouseInfo.getPointerInfo().getLocation() (see Get Mouse Position).

Then, to convert that coordinate to be relative to the jPanel, you can use SwingUtilities.convertPointFromScreen().

Here, I have updated the cursor position in an overridden updateBuffer function which then calls its parent to draw everything. Note that, I only update the hover position when the scrollbar is being dragged (e.g. areLabelsBeingScrolled()) which simply returns a boolean that is set to true when the mouse clicks on a scrollbar and set to false when it is released.

@Override
public void updateBuffer(final Graphics g,final Dimension offscreenSize) {
    if(areLabelsBeingScrolled()) {
        Point p = MouseInfo.getPointerInfo().getLocation();
        SwingUtilities.convertPointFromScreen(p,getComponent());
        debug("Cursor x coordinate relative to column labels: [" + p.x + "]",8);
        int hDI = map.getIndex(p.x); //Hover Data Index
        if(hDI > map.getMaxIndex()) {
            hDI = map.getMaxIndex();
        } else if (hDI < 0) {
            hDI = 0;
        }
        map.setHoverIndex(hDI);
    }
    super.updateBuffer(g,offscreenSize);
}

As you can see from this screen recording, it works quite well:

https://dl.dropboxusercontent.com/u/87939936/StackOverflow/getX_on_scrollbar_drag_answer.mov

Furthermore, to make cursor hovering changes smooth, I use a timer that causes updateBuffer to update continuously during the scrolling period. But that is ancillary to the question, so I won't go into further detail about it.

Community
  • 1
  • 1
hepcat72
  • 890
  • 4
  • 22
0
private void labelMousePressed(java.awt.event.MouseEvent evt) {                                    
    xMouse = evt.getX();
    yMouse = evt.getY();
} 

From this code you can get position of cursor when it is pressed on a label.

I hope this helps you.

Programmer
  • 445
  • 4
  • 12