Solved

JFrame + mouseListener

Posted on 2002-05-20
7
1,673 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
ScreenConnect 6.0 Free Trial

Want empowering updates? You're in the right place! Discover new features in ScreenConnect 6.0, based on partner feedback, to keep you business operating smoothly and optimally (the way it should be). Explore all of the extras and enhancements for yourself!

 
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

ScreenConnect 6.0 Free Trial

Want empowering updates? You're in the right place! Discover new features in ScreenConnect 6.0, based on partner feedback, to keep you business operating smoothly and optimally (the way it should be). Explore all of the extras and enhancements for yourself!

Question has a verified solution.

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

Suggested Solutions

By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand columnThat will then direct you to their download page.From that page s…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…

777 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