Thallius
Thallius

Reputation: 2619

GlassPane dispatch mouse events correctly

I am using a GlassPane to move elements in my frame. When there is no element dragged all mouse events are dispatched by the normal way

public class MainFrame implements MouseListener {
 private JFrame frame;

 public MainFrame()
 {
    frame = new JFrame();

    JPanel testPanel = new JPanel();
    testPanel.addMouseListener(this);

    JLabel testLabel = new JLabel("Test",JLabel.CENTER);
    testPanel.add(testLabel);

    frame.add(testPanel);
    frame.pack();
    frame.setVisible(true);

    GlassPanel glassPanel = new GlassPanel(frame);
    frame.setGlassPane(glassPanel);
    // Without this line the click in the panel is mentioned.
    // otherwise it is ignored.
    frame.getGlassPane().setVisible(true);
 }

 @Override
 public void mouseClicked(MouseEvent e) 
 {
    System.out.print("CLicked");
 }

 @Override
 public void mousePressed(MouseEvent e) {
    // TODO Auto-generated method stub

 }

 @Override
 public void mouseReleased(MouseEvent e) {
    // TODO Auto-generated method stub

 }

 @Override
 public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub

 }

 @Override
 public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub

 }

 public class GlassPanel extends JPanel implements MouseMotionListener, MouseListener
 {
    private JFrame frame;

    public GlassPanel(JFrame mainframe)
    {
        frame = mainframe;

        setLayout(null);
        setOpaque(false);

        addMouseMotionListener(this);
        addMouseListener(this);

    }

    @Override
    public void mouseClicked(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mousePressed(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseReleased(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseEntered(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseExited(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseDragged(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseMoved(MouseEvent e) 
    {
            redispatchMouseEvent(e, true);
    } 

    private void redispatchMouseEvent(MouseEvent e, boolean repaint) 
    {
        System.out.println("Dispatch");
        Point glassPanePoint = e.getPoint();
        Container container = frame.getContentPane();
        Point containerPoint = SwingUtilities.convertPoint(frame.getGlassPane(),
                glassPanePoint, container);

        if (containerPoint.y < 0) { // we're not in the content pane
            // Could have special code to handle mouse events over
            // the menu bar or non-system window decorations, such as
            // the ones provided by the Java look and feel.
        } else {
            // The mouse event is probably over the content pane.
            // Find out exactly which component it's over.
            Component component = SwingUtilities.getDeepestComponentAt(
                    container, containerPoint.x, containerPoint.y);

            if (component != null) {
                // Forward events to component below
                Point componentPoint = SwingUtilities.convertPoint(
                        frame.getGlassPane(), glassPanePoint, component);
                component.dispatchEvent(new MouseEvent(component, e
                        .getID(), e.getWhen(), e.getModifiers(),
                        componentPoint.x, componentPoint.y, e
                                .getClickCount(), e.isPopupTrigger()));
            }
        }
    }
 }
}

But this leads to unnormal behaviour in the mouse event handling. For example: I have a JPanel with a mouse listener. Double clicking on this panel opens an other frame. On this Panel there are some labels. When there is no Glasspane, I can click on this labels and, because labels do not act on mouse events, the event is passed through to the panel and the click action is done. When I use my dispatch routine, I dispatch the mouse event directly to the label, which of couse leads to no action.

So how can I fix this? Of course I can create my own label class with an reference to its Panel and dispatch the mouse events again to the panel, but that looks not like a nice design. the second though is, that I can determine in the Glasspane dispatcher, if the deepest panel is interesstet in mouse events and if not, step up higher or something like that?

Any ideas?

Upvotes: 2

Views: 577

Answers (0)

Related Questions