Results 1 to 16 of 16
  1. #1
    Mate de Vita is offline Member
    Join Date
    Mar 2012
    Posts
    63
    Rep Power
    0

    Default Glass Pane doesn't intercept events

    I made a translucent Glass Pane that's supposed to cover my application while the application is working out a solution:
    Java Code:
    public class MyGlassPane extends JComponent {
        private static MyGlassPane instance = new MyGlassPane();
        private Timer timer;
    
        private MyGlassPane() {
            setBackground (Color.WHITE);
    
            timer = new Timer (100, new ActionListener() {
                @Override
                public void actionPerformed (ActionEvent e) {
                    //do some animation-related stuff
                    repaint();
                }
            });
    
            addMouseListener (new MouseAdapter(){});
            addKeyListener (new KeyAdapter(){});
        }
        
        public static MyGlassPane getInstance() {
            return instance;
        }
        
        @Override
        public void setVisible (boolean visible) {
            super.setVisible (visible);
            if (visible) timer.start();
            else timer.stop();
        }
        
        @Override
        protected void paintComponent (Graphics g) {
            Rectangle clip = g2d.getClipBounds();
            g2d.setComposite (AlphaComposite.SrcOver.derive (0.65f));
            g2d.setColor (getBackground());
            g2d.fillRect (clip.x, clip.y, clip.width, clip.height);
            
            //paint an animation
        }
    }
    Now I've seen some mentions that a Glass Pane is supposed to intercept events while it's visible and not let them through to the components below (that's why I added the MouseAdapter and KeyAdapter). However, my Glass Pane only blocks mouse events, not key events, despite both listeners being added. Is this how a glass pane is supposed to act or is there something I'm doing wrong?

    I could add a listenersEnabled = !visible to the setVisible method (since I already have a listenersEnabled flag in my MainPanel class).
    However that won't disable JMenuBar key events, so if there's an easy way to make Glass Pane block key events as well, I'd rather use that. Also since I already use that flag for some other logic, it might clash, enabling listeners at inappropriate times.


    Also, as a side note, the paintComponent code that I have here was copied from somewhere, and I'd like to know why it uses g2d.getClipBounds() and then clip.x, clip.y, clip.width, clip.height.
    I get the same result if I use 0, 0, getWidth() and getHeight() and even the application I used as a reference used getWidth() and getHeight() afterwards for everything else.
    So what is the reason to use getClipBounds() for that particular part?

  2. #2
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    3,600
    Rep Power
    5

    Default Re: Glass Pane doesn't intercept events

    Where are your Mouse and Key listener implementations?

    Regards,
    Jim
    The Java™ Tutorial | SSCCE | Java Naming Conventions
    Poor planning our your part does not constitute an emergency on my part.

  3. #3
    Mate de Vita is offline Member
    Join Date
    Mar 2012
    Posts
    63
    Rep Power
    0

    Default Re: Glass Pane doesn't intercept events

    They're in the MainPanel class, defined in the ImagePanel's constructor.

    MyMenuBar also has an ActionListener for the JMenuItem items, as well as its own default KeyListener (for ALT key) and MouseListener (clicking on JMenu), which I would also like to block if possible.

    Java Code:
    public class Main {
        public static void main (String[] args) {
            SwingUtilities.invokeLater (new Runnable() {
                public void run() {
                    createGUI();
                }
            });
        }
        
        private static void createGUI() {
            try {
                UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName());
            }
            catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
                e.printStackTrace();
            }
    
            JFrame frame = new JFrame ("ASFD");
            frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
            
            frame.setJMenuBar (new MyMenuBar());
            frame.setContentPane (MainPanel.getInstance());
            frame.setGlassPane (MyGlassPane.getInstance());
            
            frame.pack();
            frame.setResizable (false);
            frame.setLocationRelativeTo (null);
            frame.setVisible (true);
        }
    }
    
    
    
    
    
    public class MainPanel extends JPanel {
        public static int SIZE = 420;
        private static MainPanel instance = new MainPanel();
        
        private MainPanel() {
            super();
            setPreferredSize (new Dimension (SIZE + 10, SIZE + 10));
            add (new ImagePanel());
        }
    
        public static MainPanel getInstance() {
            return instance;
        }
        
        private class ImagePanel extends JPanel {
            boolean listenersEnabled;    //currently a flag to disable listeners while the logic behind a move is being executed
            
            ImagePanel() {
                super();
                setPreferredSize (new Dimension (SIZE, SIZE));
                setFocusable (true);
                
                listenersEnabled = true;
                
                addMouseListener (new MouseAdapter() {
                    @Override
                    public void mousePressed (MouseEvent e) {
                        if (!listenersEnabled) return;
                        
                        System.out.println ("Mouse clicked");    //calculate stuff
                        
                        move();
                    }
                });
                
                addKeyListener (new KeyAdapter() {
                    @Override
                    public void keyPressed (KeyEvent e) {
                        if (!listenersEnabled || MyGlassPane.getInstance().isVisible()) return;        //the isVisible() check is how I'm blocking key events atm
                        
                        System.out.println ("Key pressed");      //calculate stuff
                            
                        move();
                    }
                });
            }
            
            private void move() {
                listenersEnabled = false;
                //calculate stuff
                listenersEnabled = true;
                //animate stuff
            }
    
            @Override
            public void paintComponent (Graphics g) {
                super.paintComponent (g);
                Graphics2D g2d = (Graphics2D)g;
                g2d.setColor (Color.BLUE);
                g2d.fillRect (10, 10, 200, 200);    //an image is actually drawn here
            }
        }
    }
    
    
    
    
    
    public class MyMenuBar extends JMenuBar implements ActionListener {
        JMenu file;
        JMenuItem solve;
        
        public MyMenuBar() {
            super();
            
            solve = new JMenuItem ("Solve");
            solve.addActionListener (this);
            file = new JMenu ("File");
            file.add (solve);
            add (file);
        }
    
    
        public void actionPerformed (ActionEvent e) {
            JMenuItem source = (JMenuItem)e.getSource();
            if (source.equals (solve)) solve();
        }
        
        private void solve() {
            MyGlassPane.getInstance().setVisible (true);
            //find a solution (on a different Thread)
            //MyGlassPane.getInstance().setVisible (false);
            //execute the solution
        }
    }
    
    
    
    
    
    public class MyGlassPane extends JComponent {
        private static MyGlassPane instance = new MyGlassPane();
        private Timer timer;
         
        private MyGlassPane() {
            setBackground (Color.WHITE);
         
            timer = new Timer (100, new ActionListener() {
                @Override
                public void actionPerformed (ActionEvent e) {
                    //do some animation-related stuff
                    repaint();
                 }
             });
         
            addMouseListener (new MouseAdapter(){});
            addKeyListener (new KeyAdapter(){});
        }
             
        public static MyGlassPane getInstance() {
            return instance;
        }
             
        @Override
        public void setVisible (boolean visible) {
            super.setVisible (visible);
            if (visible) timer.start();
            else timer.stop();
        }
             
        @Override
        protected void paintComponent (Graphics g) {
            Graphics2D g2d = (Graphics2D)g;
            Rectangle clip = g2d.getClipBounds();
            g2d.setComposite (AlphaComposite.SrcOver.derive (0.65f));
            g2d.setColor (getBackground());
            g2d.fillRect (clip.x, clip.y, clip.width, clip.height);
                 
            //paint an animation
        }
    }
    Last edited by Mate de Vita; 04-07-2014 at 05:16 PM. Reason: edited to make it compilable

  4. #4
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    3,600
    Rep Power
    5

    Default Re: Glass Pane doesn't intercept events

    Uh, your code doesn't even compile. Even if you provide the MyGlassPane class (which you didn't), in line 36 above you are trying to instantiate Image which is an abstract class. You cannot do that.

    Regards,
    Jim
    The Java™ Tutorial | SSCCE | Java Naming Conventions
    Poor planning our your part does not constitute an emergency on my part.

  5. #5
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default Re: Glass Pane doesn't intercept events

    KeyEvents are dispatched to the component that has focus.

    Take a look at Disabled Glass Pane « Java Tips Weblog. The code:

    1. uses the requestFocusInWindow() method to make sure the glass pane has focus
    2. use the KeyListener to consume the KeyEvents.

  6. #6
    Mate de Vita is offline Member
    Join Date
    Mar 2012
    Posts
    63
    Rep Power
    0

    Default Re: Glass Pane doesn't intercept events

    Quote Originally Posted by jim829 View Post
    Uh, your code doesn't even compile. Even if you provide the MyGlassPane class (which you didn't), in line 36 above you are trying to instantiate Image which is an abstract class. You cannot do that.

    Regards,
    Jim
    MyGlassPane is the first class I provided in this thread, edited my second post now to include it. Also edited the code itself into hopefully being compilable.

  7. #7
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    3,600
    Rep Power
    5

    Default Re: Glass Pane doesn't intercept events

    Okay, your program will respond to mouse events and key events when run. When I click on "File -> solve" it doesn't respond to any events. I had to
    add a cast to your paintComponent() to cast to Graphics2D. Otherwise. it wouldn't compile.

    Now what am I supposed to see when I run this program?

    Regards,
    Jim
    The Java™ Tutorial | SSCCE | Java Naming Conventions
    Poor planning our your part does not constitute an emergency on my part.

  8. #8
    Mate de Vita is offline Member
    Join Date
    Mar 2012
    Posts
    63
    Rep Power
    0

    Default Re: Glass Pane doesn't intercept events

    Quote Originally Posted by camickr View Post
    KeyEvents are dispatched to the component that has focus.

    Take a look at Disabled Glass Pane « Java Tips Weblog. The code:

    1. uses the requestFocusInWindow() method to make sure the glass pane has focus
    2. use the KeyListener to consume the KeyEvents.
    This does work for KeyEvents to the ImagePanel, however ALT key KeyEvents (ie. key events that activate menus in the JMenuBar) still get through to MyMenuBar. Is there a way to block those?

    Quote Originally Posted by jim829 View Post
    Okay, your program will respond to mouse events and key events when run. When I click on "File -> solve" it doesn't respond to any events. I had to
    add a cast to your paintComponent() to cast to Graphics2D. Otherwise. it wouldn't compile.

    Now what am I supposed to see when I run this program?

    Regards,
    Jim
    Both paintComponent() methods include a cast to Graphics2D, I'm not sure why it wouldn't compile for you? It compiled for me.

    You are supposed to see a panel with a blue square painted on it, that responds to MouseEvents and KeyEvents by printing to std output, as well as a JMenuBar that responds to MouseEvents and KeyEvents, with a JMenu File, which includes a JMenuItem Solve.
    When you click File -> Solve, a translucent glass panel should show up over it, and block any KeyEvents and MouseEvents. Currently it doesn't block KeyEvents to MyMenuBar, as mentioned above.
    Last edited by Mate de Vita; 04-07-2014 at 05:42 PM.

  9. #9
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    3,600
    Rep Power
    5

    Default Re: Glass Pane doesn't intercept events

    Upon further review, what are you trying to do here? Do you realize that these commands don't do anything because the methods are not implemented?

    Java Code:
    addMouseListener (new MouseAdapter(){});
    addKeyListener (new KeyAdapter(){});
    Regards,
    Jim
    The Java™ Tutorial | SSCCE | Java Naming Conventions
    Poor planning our your part does not constitute an emergency on my part.

  10. #10
    Mate de Vita is offline Member
    Join Date
    Mar 2012
    Posts
    63
    Rep Power
    0

    Default Re: Glass Pane doesn't intercept events

    I realize that the methods are implemented to do nothing, yes. Doing nothing is exactly how I want my Glass Pane to respond to events.

  11. #11
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    3,600
    Rep Power
    5

    Default Re: Glass Pane doesn't intercept events

    Well, it does not respond to events (at least for me) when I click on "solve." I just get a semi-transparent screen and no response to the keyboard or mouse.

    Regards,
    Jim
    The Java™ Tutorial | SSCCE | Java Naming Conventions
    Poor planning our your part does not constitute an emergency on my part.

  12. #12
    Mate de Vita is offline Member
    Join Date
    Mar 2012
    Posts
    63
    Rep Power
    0

    Default Re: Glass Pane doesn't intercept events

    Hmm... removing the KeyListener line had no effect, but if I remove the MouseListener line, MouseEvents get through the visible Glass Pane to the ImagePanel below (I get the "Mouse clicked" message even after clicking file->solve).

    Also I've noticed that ALT only activates JMenus when I use the System Look and Feel (currently on a Windows computer), and not when I use Java's default. Are you running another OS perhaps?

  13. #13
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default Re: Glass Pane doesn't intercept events

    however ALT key KeyEvents (ie. key events that activate menus in the JMenuBar) still get through to MyMenuBar. Is there a way to block those?
    It works fine for me on Windows 7 using JDK7. Did you try my class?

  14. #14
    Mate de Vita is offline Member
    Join Date
    Mar 2012
    Posts
    63
    Rep Power
    0

    Default Re: Glass Pane doesn't intercept events

    I changed the setVisible method in MyGlassPane to
    Java Code:
    public void setVisible (boolean visible) {
        super.setVisible (visible);
        if (visible) {
            requestFocusInWindow();    //give focus to glass pane to direct KeyEvents to it
            timer.start();
        }
        else {
            MainPanel.getInstance().requestFocusInWindow();    //give focus back to the main panel
            timer.stop();
        }
    }
    and overrode MainPanel's requestFocusInWindow() to redirect focus to the ImagePanel (where the actual listeners are).

    It works great, except for the alt key. If I press alt while MyGlassPane is visible, it still registers it and takes me into the JMenuBar where I can then use the arrow keys to select any JMenu and JMenuItem.

    Are you using the System L&F? Because this only happens to me when I'm using it. It doesn't happen with Java's default L&F.

  15. #15
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default Re: Glass Pane doesn't intercept events

    I tested the DisabledPane class using Windows and the Metal LAF. You still haven't answered my question.

  16. #16
    Mate de Vita is offline Member
    Join Date
    Mar 2012
    Posts
    63
    Rep Power
    0

    Default Re: Glass Pane doesn't intercept events

    Oh, I neglected to consume() the KeyEvents, as you do in your class, my bad. It properly blocks all KeyEvents as expected now. Thanks!

Similar Threads

  1. Replies: 10
    Last Post: 05-08-2012, 05:17 AM
  2. My code doesn't work! Pane.showOptionDialog()
    By 0070071 in forum AWT / Swing
    Replies: 5
    Last Post: 01-18-2012, 05:56 AM
  3. Draw button with glass effect
    By AlirezaM in forum CLDC and MIDP
    Replies: 0
    Last Post: 05-18-2011, 08:55 PM
  4. Painting onto Aero Glass
    By Andolamin in forum SWT / JFace
    Replies: 0
    Last Post: 06-02-2010, 04:49 PM
  5. typed events vs untyped events.
    By Drun in forum SWT / JFace
    Replies: 0
    Last Post: 11-23-2009, 12:22 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •