Results 1 to 9 of 9
  1. #1
    kjkrum's Avatar
    kjkrum is offline Senior Member
    Join Date
    Apr 2011
    Location
    Tucson, AZ
    Posts
    1,060
    Rep Power
    6

    Default Making an invisible JButton that appears under the mouse pointer

    I'm trying to make a component with an invisible button that appears when you hover the mouse over it. I'm using a JLayeredPane and I've succeeded in making a floating JPanel with a JLabel appear and disappear the way I want. This much works perfectly. However, if I replace the JLabel with a JButton, then whenever the mouse moves within the JButton, the JPanel's MouseListener is spammed with mouse entered/exited events, causing the JButton to flicker.

    I suppose the JButton has its own MouseListener, but why would that cause its parent to receive spurious mouse events?

    SSCCE:

    Java Code:
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JLayeredPane;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    
    public class LayeredPanes {
    
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(new Runnable() {
    			@Override
    			public void run() {
    				JPanel bluePanel = new JPanel();
    				bluePanel.setBackground(Color.BLUE);
    				bluePanel.setBounds(0, 0, 500, 300);
    				
    				final JPanel redPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    				redPanel.setBackground(Color.red);
    				redPanel.setBounds(100, 75, 300, 150);
    				
    				final JLabel label = new JLabel("my label");
    				label.setForeground(Color.white);
    				label.setVisible(false);
    				redPanel.add(label);
    				
    				
    				// make the red panel invisible until the mouse hovers over it
    				redPanel.setOpaque(false);
    				redPanel.addMouseListener(new MouseAdapter() {
    
    					@Override
    					public void mouseEntered(MouseEvent e) {
    						redPanel.setOpaque(true);
    						label.setVisible(true);
    						redPanel.repaint();
    					}
    
    					@Override
    					public void mouseExited(MouseEvent e) {
    						redPanel.setOpaque(false);
    						label.setVisible(false);
    						redPanel.repaint();
    					}
    					
    				});
    
    				JLayeredPane layeredPane = new JLayeredPane();
    				layeredPane.add(bluePanel, new Integer(0));
    				layeredPane.add(redPanel, new Integer(1));
    				layeredPane.setPreferredSize(bluePanel.getSize());
    				
    				JFrame frame = new JFrame("Layers");
    				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    				frame.setContentPane(layeredPane);
    				frame.pack();
    				frame.setVisible(true);
    			}
    		});
    	}
    }
    Last edited by kjkrum; 04-04-2012 at 12:19 AM.
    Get in the habit of using standard Java naming conventions!

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default Re: Making an invisible JButton that appears under the mouse pointer

    If a component has a MouseListener or MouseMotionListener and that acts as a container and holds another component with the same listeners, then the component with the highest z-order, the one held by the container will steal the mouse from the container whenever the mouse goes over it. This will send a mouse exited message to the container. One possible solution is to use the glass pane to do all mouse listening and then dispatch messages to components under the glass pane.

  3. #3
    kjkrum's Avatar
    kjkrum is offline Senior Member
    Join Date
    Apr 2011
    Location
    Tucson, AZ
    Posts
    1,060
    Rep Power
    6

    Default Re: Making an invisible JButton that appears under the mouse pointer

    But the container isn't just receiving a single mouse exited event when the pointer enters the button. It's being continuously spammed with mouse entered and exited events as the pointer moves around inside the button. I'd like to understand why this is happening.
    Get in the habit of using standard Java naming conventions!

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default Re: Making an invisible JButton that appears under the mouse pointer

    Hm, perhaps you can create an SSCCE that shows this, something similar to this one:

    Java Code:
    import java.awt.Dimension;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    public class MouseListenerTest {
       private static void createAndShowGui() {
          JPanel panel = new JPanel();
          panel.setPreferredSize(new Dimension(200, 200));
          MyMouseAdapter panelMyMAdapter = new MyMouseAdapter("panel");
          panel.addMouseListener(panelMyMAdapter);
          panel.addMouseMotionListener(panelMyMAdapter);
          panel.setBorder(BorderFactory.createTitledBorder("panel"));
          
          JButton button = new JButton("Button");
          MyMouseAdapter btnMyMAdapter = new MyMouseAdapter("button");
          button.addMouseListener(btnMyMAdapter);
          button.addMouseMotionListener(btnMyMAdapter);
          
          panel.add(button);
          
          JOptionPane.showMessageDialog(null, panel);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    class MyMouseAdapter extends MouseAdapter {
       private String componentName;
    
       public MyMouseAdapter(String componentName) {
          this.componentName = componentName;
       }
       
       @Override
       public void mouseEntered(MouseEvent arg0) {
          System.out.println(componentName + " entered");
       }
       
       @Override
       public void mouseExited(MouseEvent arg0) {
          System.out.println(componentName + " exited");
       }
    }
    Edit: I see your SSCCE, sorry. Let me look at it in detail.
    Last edited by Fubarable; 04-04-2012 at 01:06 AM.

  5. #5
    doWhile is offline Moderator
    Join Date
    Jul 2010
    Location
    California
    Posts
    1,642
    Rep Power
    7

    Default Re: Making an invisible JButton that appears under the mouse pointer

    I don't see the result that you describe when running the code from post #1 with a JLabel or a JButton - the MouseListener is fired once for a mouseEntered and mouseExited, when the mouse enters and exits - no continual firing the the listeners.

  6. #6
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default Re: Making an invisible JButton that appears under the mouse pointer

    A possible kludge is to add a MouseListener to the JButton, and then pass the mouse event on to the red panel. Something like...

    Java Code:
                // final JLabel label = new JLabel("my label");
                final JButton button = new JButton("button");
                button.setForeground(Color.white);
                button.setVisible(false);
                
                button.addMouseListener(new MouseAdapter() {
                   @Override
                   public void mouseEntered(MouseEvent e) {
                      super.mouseEntered(e);
                      MouseListener[] redPanelMListeners = redPanel.getMouseListeners();
                      int x = e.getX() + button.getX();
                      int y = e.getY() + button.getY();
                      MouseEvent redPanelmEvt = new MouseEvent(redPanel, e.getID(),
                            e.getWhen(), e.getModifiers(), x, y, e.getClickCount(),
                            e.isPopupTrigger());
                      for (MouseListener mouseListener : redPanelMListeners) {
                         mouseListener.mouseEntered(redPanelmEvt);
                      }
                   }
                });

  7. #7
    kjkrum's Avatar
    kjkrum is offline Senior Member
    Join Date
    Apr 2011
    Location
    Tucson, AZ
    Posts
    1,060
    Rep Power
    6

    Default Re: Making an invisible JButton that appears under the mouse pointer

    Here's my original code with the JLabel replaced by a JButton. Moving the pointer in and out of the red panel still fires events as expected, but things get weird when I mouse over the button.

    Java Code:
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLayeredPane;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class LayeredPanes {
    
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(new Runnable() {
    			@Override
    			public void run() {
    				JPanel bluePanel = new JPanel();
    				bluePanel.setBackground(Color.BLUE);
    				bluePanel.setBounds(0, 0, 500, 300);
    				
    				final JPanel redPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    				redPanel.setBackground(Color.red);
    				redPanel.setBounds(100, 75, 300, 150);
    				
    				final JButton button = new JButton("my button");
    				
    				button.setVisible(false);
    				redPanel.add(button);
    				
    				// make the red panel invisible until the mouse hovers over it
    				redPanel.setOpaque(false);
    				redPanel.addMouseListener(new MouseAdapter() {
    
    					@Override
    					public void mouseEntered(MouseEvent e) {
    						System.out.println("mouse entered");
    						redPanel.setOpaque(true);
    						button.setVisible(true);
    						redPanel.repaint();
    					}
    
    					@Override
    					public void mouseExited(MouseEvent e) {
    						System.out.println("mouse exited");
    						redPanel.setOpaque(false);
    						button.setVisible(false);
    						redPanel.repaint();
    					}
    					
    				});
    
    				JLayeredPane layeredPane = new JLayeredPane();
    				layeredPane.add(bluePanel, new Integer(0));
    				layeredPane.add(redPanel, new Integer(1));
    				layeredPane.setPreferredSize(bluePanel.getSize());
    				
    				JFrame frame = new JFrame("Layers");
    				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    				frame.setContentPane(layeredPane);
    				frame.pack();
    				frame.setVisible(true);
    			}
    		});
    	}
    }
    Get in the habit of using standard Java naming conventions!

  8. #8
    kjkrum's Avatar
    kjkrum is offline Senior Member
    Join Date
    Apr 2011
    Location
    Tucson, AZ
    Posts
    1,060
    Rep Power
    6

    Default Re: Making an invisible JButton that appears under the mouse pointer

    I also may have found a solution. I added the mouse motion listener to the JPanel in layer 0, which I'm calling the content pane. When the mouse moves into the bounds of the button, the button is added to layer 1 and it begins intercepting mouse events. When the pointer moves out of the button, the content pane again receives mouse events and it removes the button.

    Java Code:
    import java.awt.Color;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionAdapter;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLayeredPane;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class LayeredPanes2 {
    
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(new Runnable() {
    			@Override
    			public void run() {
    				final JPanel contentPane = new JPanel();
    				contentPane.setBackground(Color.BLUE);
    				contentPane.setBounds(0, 0, 500, 300);
    
    				final JLayeredPane layeredPane = new JLayeredPane();
    				layeredPane.add(contentPane, new Integer(0));
    				layeredPane.setPreferredSize(contentPane.getSize());
    
    				final JButton button = new JButton("My Secret Button");
    				button.setSize(button.getPreferredSize());
    				button.setLocation(10, 10);
    
    				contentPane.addMouseMotionListener(new MouseMotionAdapter() {
    					@Override
    					public void mouseMoved(MouseEvent e) {
    						if (button.getBounds().contains(e.getPoint())) {
    							layeredPane.add(button, new Integer(1));
    						} else {
    							layeredPane.remove(button);
    							layeredPane.repaint();
    						}
    					}
    				});
    
    				JFrame frame = new JFrame("Layers");
    				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    				frame.setContentPane(layeredPane);
    				frame.pack();
    				frame.setVisible(true);
    			}
    		});
    	}
    
    }
    Get in the habit of using standard Java naming conventions!

  9. #9
    kjkrum's Avatar
    kjkrum is offline Senior Member
    Join Date
    Apr 2011
    Location
    Tucson, AZ
    Posts
    1,060
    Rep Power
    6

    Default Re: Making an invisible JButton that appears under the mouse pointer

    Improved the mouse motion listener so the component isn't constantly repainted when the mouse moves around:

    Java Code:
    				contentPane.addMouseMotionListener(new MouseMotionAdapter() {
    					boolean buttonVisible = false;
    					
    					@Override
    					public void mouseMoved(MouseEvent e) {
    						if (button.getBounds().contains(e.getPoint())) {
    							layeredPane.add(button, new Integer(1));
    							buttonVisible = true;
    						} else if(buttonVisible) {
    							layeredPane.remove(button);
    							layeredPane.repaint();
    							buttonVisible = false;
    						}
    					}
    				});
    Get in the habit of using standard Java naming conventions!

Similar Threads

  1. creating an invisible JButton
    By kratos27 in forum AWT / Swing
    Replies: 3
    Last Post: 01-28-2011, 04:47 PM
  2. Replies: 6
    Last Post: 09-08-2010, 12:58 PM
  3. Replies: 2
    Last Post: 04-14-2009, 10:01 PM
  4. mouse over on JButton
    By gradon in forum Java Applets
    Replies: 1
    Last Post: 08-04-2007, 05:50 AM
  5. Mouse over JButton
    By sandor in forum AWT / Swing
    Replies: 1
    Last Post: 05-17-2007, 09:15 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •