最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - swing overlay panel - Stack Overflow

programmeradmin4浏览0评论

I want to create a panel that act as an overlay and react to the mouse position (Here represented by drawing a circle at the mouse position)

But when I add a mouseMotionListener to the overlay panel it stops mouse event from being received by the components under the overlay. What would be a solution for that ? I tried with dispatchEvent but it didn't create mouseEntered and mouseExited events.

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

public class MWE extends JFrame
{

    public class LinePanel extends JPanel
    {
        int mouseX;
        int mouseY;
        
        public LinePanel()
        {
            mouseX = 100;
            mouseY = 100;
            this.addMouseMotionListener(new MouseMotionListener() {
                public void mouseMoved(MouseEvent e) 
                {
                    mouseX = e.getX();
                    mouseY = e.getY();
                    repaint();
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                };
            });
            this.setOpaque(false);
            this.setLayout(null);
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            
            g.drawOval(mouseX - 10, mouseY  - 10, 20, 20);
        }
    }

    public MWE()
    {
        JLayeredPane layeredPane = new JLayeredPane();

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.PAGE_AXIS));
        
        JButton button = new JButton("Foo");
        button.addMouseListener(new MouseInputAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                super.mouseEntered(e);
                button.setBackground(Color.red);
            }

            @Override
            public void mouseExited(MouseEvent e) {
                super.mouseExited(e);
                button.setBackground(null);
            }
        });

        button.setAlignmentX(JButton.CENTER_ALIGNMENT);

        buttonPanel.add(Box.createVerticalGlue());
        buttonPanel.add(button);
        buttonPanel.add(Box.createVerticalGlue());

        JPanel linePanel = new LinePanel();

        layeredPane.add(buttonPanel, Integer.valueOf(0));
        layeredPane.add(linePanel, Integer.valueOf(1));

        layeredPane.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                buttonPanel.setBounds(layeredPane.getBounds());
                linePanel.setBounds(layeredPane.getBounds());
                
                buttonPanel.revalidate();
            }
        });

        this.setContentPane(layeredPane);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args)
    {
        MWE frame = new MWE();
        frame.setVisible(true);
    }
}

I want to create a panel that act as an overlay and react to the mouse position (Here represented by drawing a circle at the mouse position)

But when I add a mouseMotionListener to the overlay panel it stops mouse event from being received by the components under the overlay. What would be a solution for that ? I tried with dispatchEvent but it didn't create mouseEntered and mouseExited events.

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

public class MWE extends JFrame
{

    public class LinePanel extends JPanel
    {
        int mouseX;
        int mouseY;
        
        public LinePanel()
        {
            mouseX = 100;
            mouseY = 100;
            this.addMouseMotionListener(new MouseMotionListener() {
                public void mouseMoved(MouseEvent e) 
                {
                    mouseX = e.getX();
                    mouseY = e.getY();
                    repaint();
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                };
            });
            this.setOpaque(false);
            this.setLayout(null);
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            
            g.drawOval(mouseX - 10, mouseY  - 10, 20, 20);
        }
    }

    public MWE()
    {
        JLayeredPane layeredPane = new JLayeredPane();

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.PAGE_AXIS));
        
        JButton button = new JButton("Foo");
        button.addMouseListener(new MouseInputAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                super.mouseEntered(e);
                button.setBackground(Color.red);
            }

            @Override
            public void mouseExited(MouseEvent e) {
                super.mouseExited(e);
                button.setBackground(null);
            }
        });

        button.setAlignmentX(JButton.CENTER_ALIGNMENT);

        buttonPanel.add(Box.createVerticalGlue());
        buttonPanel.add(button);
        buttonPanel.add(Box.createVerticalGlue());

        JPanel linePanel = new LinePanel();

        layeredPane.add(buttonPanel, Integer.valueOf(0));
        layeredPane.add(linePanel, Integer.valueOf(1));

        layeredPane.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                buttonPanel.setBounds(layeredPane.getBounds());
                linePanel.setBounds(layeredPane.getBounds());
                
                buttonPanel.revalidate();
            }
        });

        this.setContentPane(layeredPane);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args)
    {
        MWE frame = new MWE();
        frame.setVisible(true);
    }
}
Share asked Mar 5 at 18:40 SeirynSeiryn 33 bronze badges 8
  • 1 See also How to Use Root Panes: The Glass Pane – trashgod Commented Mar 6 at 0:00
  • if you add a event listener on mouseEntered for any component in the content pane you'll see that they don't fire when the glass pane is present – Seiryn Commented Mar 6 at 8:12
  • See redispatchMouseEvent() in the _ GlassPaneDemo_. – trashgod Commented Mar 6 at 14:02
  • You can do the test with this demo : See how when you over the components they react : this is because they receive a mouseEntered event. When the glassPane is "visible" they don't react anymore, even the checkbox, which shoud still have events forwarded – Seiryn Commented Mar 8 at 10:22
  • 1 JLayer is designed for such use cases… – Holger Commented Mar 10 at 17:09
 |  Show 3 more comments

1 Answer 1

Reset to default 1

have you tried to dispatch the event inside the line panel?

linePanel.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
    
    buttonPanel.dispatchEvent(SwingUtilities.convertMouseEvent(linePanel, e, buttonPanel));
}

});

发布评论

评论列表(0)

  1. 暂无评论