Search code examples
javaswingmouseeventjsplitpane

jSplitPane Showing and Hiding Left Pane when Mouse over


I'm working on an application that allows me to show and hide split planes. I've read some articles on how to get this but its not what I'm looking for.

here's the code Ive written:

Im currently using netbeans.

private void jSplitPane1MouseEntered(java.awt.event.MouseEvent evt) {                                         
        if(MouseInfo.getPointerInfo().getLocation() == jSplitPane1.getLeftComponent().getLocation()){
           jSplitPane1.setDividerLocation(100);
           System.out.println("Mouse Entered");
       }else{
           jSplitPane1.setDividerLocation(20);
           System.out.println("Mouse Exited");
       }
    } 

I have referred to these posts:

How to make JSplitPane auto expand on mouse hover?

Get Mouse Position

What I want to happen is when I mouse over the left side of the jSplitPane, I would get the divider to extend to 100 as per my first if statement, and when it exists the left side, it contracts back to divider location 20.


Solution

  • This is really, really tricky.

    You could use a MouseListener on the "left" component and monitor the mouseEntered and mouseExited events, but these will also get triggered when when you move into and out of a child component which has a MouseListener of it's own (like a JButton).

    Okay, you could use a MouseMotionListener on the JSplitPane and monitor for the mouseMoved event and check where the mouse cursor is, but this goes to hell the moment the components (left/right) get their own MouseListener, as the MouseEvents are no longer delivered to the JSplitPane

    So, one of the last options you have is to attach a global AWTListener to the event queue and monitor for events which occur on the JSplitPane itself, for example...

    SplitPane

    import java.awt.AWTEvent;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.GridBagLayout;
    import java.awt.Toolkit;
    import java.awt.event.AWTEventListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JSplitPane;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Main {
    
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(new BorderLayout());
    
                JSplitPane pane = new JSplitPane();
                pane.setLeftComponent(makePane(Color.RED));
                pane.setRightComponent(makePane(Color.BLUE));
    
                Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
                    @Override
                    public void eventDispatched(AWTEvent event) {
                        if (event instanceof MouseEvent) {
                            MouseEvent me = (MouseEvent) event;
                            if (pane.getBounds().contains(me.getPoint())) {
                                System.out.println("Global Motion in the pane...");
                                me = SwingUtilities.convertMouseEvent(me.getComponent(), me, pane);
                                Component left = pane.getLeftComponent();
                                if (left.getBounds().contains(me.getPoint())) {
                                    pane.setDividerLocation(100);
                                } else {
                                    pane.setDividerLocation(20);
                                }
                            }
                        }
                    }
                }, MouseEvent.MOUSE_MOTION_EVENT_MASK);
    
                // You don't need this, this is to demonstrate
                // that mouse events aren't hitting your component
                // via the listener
                pane.addMouseMotionListener(new MouseAdapter() {
                    @Override
                    public void mouseMoved(MouseEvent e) {
                        System.out.println("Motion in the pane...");
                        Component left = pane.getLeftComponent();
                        if (left.getBounds().contains(e.getPoint())) {
                            pane.setDividerLocation(100);
                        } else {
                            pane.setDividerLocation(20);
                        }
                    }
    
                });
                pane.setDividerLocation(20);
    
                add(pane);
            }
    
            protected JPanel makePane(Color background) {
                JPanel pane = new JPanel() {
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(100, 100);
                    }
                };
                pane.setLayout(new GridBagLayout());
                pane.add(new JButton("..."));
                pane.setBackground(background);
                pane.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        System.out.println("...");
                    }
                });
                return pane;
            }
    
        }
    
    }