Solved

JFrame + mouseListener

Posted on 2002-05-20
7
1,666 Views
Last Modified: 2013-11-23
Hi,

I have a java applet which loads a JFrame
now this JFrame has many components

When I press a button , it loads a JWindow

if this JWindow is visible then I want to hide it
if the user presses either the escape key anywhere in the frame or if he clicks a mouse anywhere in the frame

This is the code

 /**add key listener to the root pane**/
    protected JRootPane createRootPane()
    {

        MouseListener mouseListener = new MouseAdapter()
        {
            public void mouseClicked(MouseEvent event)
            {
                setVisible(false);
            }
        };

        /**add the keyboard listener*/
        ActionListener actionListener = new ActionListener()
        {
            public void actionPerformed(ActionEvent actionEvent)
            {
                setVisible(false);
            }
        };
        JRootPane rootPane = new JRootPane();
        KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
        rootPane.registerKeyboardAction(actionListener, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);

        rootPane.addMouseListener(mouseListener);
        return rootPane;
    }


I am able to intercept the "Escape" key anywhere in the frame

But I am not able to trace mouse click events

What should I do to get the mouseClicked event
when evr user clicks the mouse anywhere in the JFrame

maybe I have to add MouseListener recursively as componets get added to the JFrame

but is there a better approcah

please help
0
Comment
Question by:sanjay_thakur
  • 4
  • 3
7 Comments
 
LVL 4

Author Comment

by:sanjay_thakur
ID: 7022174
I guess I will have to add mouseListener
for all the child components of the JFrame

but is there a better approcah?
0
 
LVL 19

Accepted Solution

by:
Jim Cakalic earned 50 total points
ID: 7022499
I'm not sure whether there is a _better_ way than what I am about to suggest. But as I recall, this way works. Basically, you have to use the GlassPane of the JFrame set to visible so that it will intercept all the mouse events occurring in the frame and redispatch (or not) to the appropriate components if desired. Here is the sample code (slightly modified) from the Java Tutorial for GlassPaneDemo that does this. The original can be found here:
    http://java.sun.com/docs/books/tutorial/uiswing/components/example-swing/index.html#GlassPaneDemo
with the relevant part of the tutorial here:
    http://java.sun.com/docs/books/tutorial/uiswing/components/rootpane.html

---------- GlassPaneDemo.java ----------
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.*;

public class GlassPaneDemo {
    static private MyGlassPane myGlassPane;

    public static void main(String[] args) {
        JFrame frame = new JFrame("GlassPaneDemo");
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        JCheckBox changeButton = new JCheckBox("Glass pane \"visible\"");
        changeButton.setSelected(false);
        changeButton.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                myGlassPane.setVisible(e.getStateChange()
                    == ItemEvent.SELECTED);
            }
        });

        JButton button1 = new JButton("Button 1");
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("Pressed Button 1");
            }
        });
        JButton button2 = new JButton("Button 2");
        button2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("Pressed Button 2");
            }
        });

        //Set up the content pane, where the "main GUI" lives.
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new FlowLayout());
        contentPane.add(changeButton);
        contentPane.add(button1);
        contentPane.add(button2);

        //Set up the menu bar, which appears above the content pane.
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("Menu");
        menu.add(new JMenuItem("Do nothing"));
        menuBar.add(menu);
        frame.setJMenuBar(menuBar);

        //Set up the glass pane, which appears over both menu bar
        //and content pane.
        myGlassPane = new MyGlassPane(changeButton, menuBar, frame.getContentPane());
        frame.setGlassPane(myGlassPane);

        frame.pack();
        frame.setVisible(true);
    }
}

/**
 * We have to provide our own glass pane so that it can paint.
 */
class MyGlassPane extends JComponent {
    Point point;

    public void paint(Graphics g) {
        if (point != null) {
            g.setColor(Color.red);
            g.fillOval(point.x - 10, point.y - 10, 20, 20);
        }
    }

    public void setPoint(Point p) {
        point = p;
    }

    public MyGlassPane(AbstractButton aButton,
        JMenuBar menuBar,
        Container contentPane) {
        CBListener listener = new CBListener(aButton, menuBar, this, contentPane);
        addMouseListener(listener);
        addMouseMotionListener(listener);
    }
}

/**
 * Listen for all events that our check box is likely to be
 * interested in.  Redispatch them to the check box.
 */
class CBListener extends MouseInputAdapter {
    Toolkit toolkit;
    Component liveButton;
    JMenuBar menuBar;
    MyGlassPane glassPane;
    Container contentPane;
    boolean inDrag = false;

    public CBListener(Component liveButton, JMenuBar menuBar,
        MyGlassPane glassPane, Container contentPane) {
        toolkit = Toolkit.getDefaultToolkit();
        this.liveButton = liveButton;
        this.menuBar = menuBar;
        this.glassPane = glassPane;
        this.contentPane = contentPane;
    }

    public void mouseMoved(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    /*
     * We must forward at least the mouse drags that started
     * with mouse presses over the check box.  Otherwise,
     * when the user presses the check box then drags off,
     * the check box isn't disarmed -- it keeps its dark
     * gray background or whatever its L&F uses to indicate
     * that the button is currently being pressed.
     */
    public void mouseDragged(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseClicked(MouseEvent e) {
        System.out.println("Mouse clicked!");
        redispatchMouseEvent(e, false);
    }

    public void mouseEntered(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseExited(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mousePressed(MouseEvent e) {
        redispatchMouseEvent(e, false);
    }

    public void mouseReleased(MouseEvent e) {
        redispatchMouseEvent(e, true);
        inDrag = false;
    }

    private void redispatchMouseEvent(MouseEvent e, boolean repaint) {
        boolean inButton = false;
        boolean inMenuBar = false;
        Point glassPanePoint = e.getPoint();
        Component component = null;
        Container container = contentPane;
        Point containerPoint = SwingUtilities.convertPoint(
            glassPane,
            glassPanePoint,
            contentPane);
        int eventID = e.getID();

        if (containerPoint.y < 0) {
            inMenuBar = true;
            container = menuBar;
            containerPoint = SwingUtilities.convertPoint(
                glassPane,
                glassPanePoint,
                menuBar);
            testForDrag(eventID);
        }

        //XXX: If the event is from a component in a popped-up menu,
        //XXX: then the container should probably be the menu's
        //XXX: JPopupMenu, and containerPoint should be adjusted
        //XXX: accordingly.
        component = SwingUtilities.getDeepestComponentAt(
            container,
            containerPoint.x,
            containerPoint.y);

        if (component == null) {
            return;
        }

        if (component.equals(liveButton)) {
            inButton = true;
            testForDrag(eventID);
        }

//        if (inMenuBar || inButton || inDrag) {
            Point componentPoint = SwingUtilities.convertPoint(
                glassPane,
                glassPanePoint,
                component);
            component.dispatchEvent(new MouseEvent(component,
                eventID,
                e.getWhen(),
                e.getModifiers(),
                componentPoint.x,
                componentPoint.y,
                e.getClickCount(),
                e.isPopupTrigger()));
//        }

        if (repaint) {
            toolkit.beep();
            glassPane.setPoint(glassPanePoint);
            glassPane.repaint();
        }
    }

    private void testForDrag(int eventID) {
        if (eventID == MouseEvent.MOUSE_PRESSED) {
            inDrag = true;
        }
    }
}
---------- end ----------

Best regards,
Jim Cakalic
0
 
LVL 4

Author Comment

by:sanjay_thakur
ID: 7024505
Hi Jim,

Is there any thing simpler

I am using jdk1.4
any new feature to handle this which I am not aware of?


0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 7024646
Nothing that I can find. Seems use of glass pane is still the way to globally intercept mouse events. I use the word "intercept" here because in AWT, a mouse action is considered to occur in a particular component if and only if the mouse cursor is over the unobscured part of the component's bounds when the action happens. Component bounds can be obscured by the visible component's children or by a menu or by a top-level window. In the case of JFrame, all the components you create and add to the content pane obscure the JFrame itself. Therefore, the JFrame, while it can be a mouse listener, will only receive mouse events when the mouse cursor is in an area not occupied by one of its child components. The glass pane is an "overlay" that, when visible, obscures everything else although it itself is by default transparent. But events cannot pass through it to the underlying components unless you choose to redispatch them directly.

Jim
0
 
LVL 4

Author Comment

by:sanjay_thakur
ID: 7027439
Hi Jim,
I guess you are correct this is the only option
I will try out the code.

Please give me a couple of days.

Thanks for all the help.
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 7027457
OK. Post back if you need anything more.
0
 
LVL 4

Author Comment

by:sanjay_thakur
ID: 7111171
My apologies for the delay.

Thanks a ton for all your help.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now