2

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?

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Thallius
  • 2,482
  • 2
  • 18
  • 36
  • 1
    You've been on this site for a while and should already know the benefits of your creating and posting a valid [mcve] rather than a non-running code snippet. Please consider improving your question by posting your mcve (as code-formatted text and not as a link of course) so that we can have a small program that we can compile, run, test and modify. – Hovercraft Full Of Eels Jul 20 '16 at 12:40
  • Ok, here we go. All Code you need to reproduce it. – Thallius Jul 20 '16 at 13:09
  • Thanks -- one possible solution -- test component if it has viable MouseListeners and MouseMotionListeners attached, and if so dispatch the event. Otherwise check the parent container/component recursively. You would want to separate out the MouseListener from the MouseMotionListener methods to do this I think, since you would need to test and dispatch these separately. – Hovercraft Full Of Eels Jul 20 '16 at 14:01
  • Thanks, but I noticed there is a much bigger disadvantage in using the GlassPane under windows. If I have JComboBoxes under the GlassPane they are also unuseable when the GlassPane is visible. On my Mac this works fine but with Windows 7 and Java 8 you can no longer scroll the ComboBox entries. Strange.... – Thallius Jul 20 '16 at 14:12
  • for me convertPoint is for scolling and convertMouseEvent is designated for GlassPane, you can use eventDispatched from AWTEventListener, for good access is required to filtering combination of Key + MouseEvent with separate KeyEvent and separate MouseEvent – mKorbel Jul 20 '16 at 19:10
  • be sure that override contains() too :-), then there you cann't lost event from GlassPane and JPanel placed somewhere deepest in the components tree – mKorbel Jul 20 '16 at 19:13
  • GlassPane doesn't protect against KeyEvent, have to decide about dispatch() or consume() – mKorbel Jul 20 '16 at 19:14

0 Answers0