0

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.

Community
  • 1
  • 1
Bumpy
  • 97
  • 11

1 Answers1

2

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;
        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • sorry for the late reply and thanks for the answer. I see its working quite nicely, but to be honest i'm not quite sure how will I add this to my app. I'm using net beans and I am not yet fully familiar with adding custom codes to components but what I understood from you code is: `1. You took the bounds of the pane and checked if it contains the current location of the mouse.` and then after that, I got confused. – Bumpy Jan 21 '16 at 05:42
  • Essentially, the first thing I did was check to see if the `MouseEvent#point` was within the bounds of the `JSplitPane`, I then converted the `MouseEvent` to the context of the `JSplitPane` and then check to see if the `MouseEvent` is within the context of the `leftPane`. `MouseEvent`s are contextual and are automatically converted to the coordinate context of the component which generates them (that is 0x0 is the top/left corner of the component) – MadProgrammer Jan 21 '16 at 05:50
  • Thanks! got it working now! thanks for explaining the concept. I just want to understand how it works before putting things in. Im gonna have to compile this since it'll be useful in the future. – Bumpy Jan 21 '16 at 07:57