Pass mouse events to applications behind from a Java UI

前端 未结 4 431
无人共我
无人共我 2021-01-03 08:11

The question I have is exactly same in requirement as How to pass mouse events to applications behind mine in C#/Vista? , but I need the same for a Transparent Java UI. I ca

相关标签:
4条回答
  • 2021-01-03 08:33

    I believe this will answer your question. To run it you will need Java 6 update 10 and above. I tested it on Windows Vista

    import java.awt.AlphaComposite;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class ClickThrough {
    
        public static void main(String[] args) {
            JFrame.setDefaultLookAndFeelDecorated(true);
            JFrame f = new JFrame("Test");
            f.setAlwaysOnTop(true);
            Component c = new JPanel() {
                @Override
                public void paintComponent(Graphics g) {
                    Graphics2D g2 = (Graphics2D)g.create();
                    g2.setColor(Color.gray);
                    int w = getWidth();
                    int h = getHeight();
                    g2.fillRect(0, 0, w,h);
                    g2.setComposite(AlphaComposite.Clear);
                    g2.fillRect(w/4, h/4, w-2*(w/4), h-2*(h/4));
                }
            };
            c.setPreferredSize(new Dimension(300, 300));
            f.getContentPane().add(c);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.pack();
            f.setVisible(true);
            com.sun.awt.AWTUtilities.setWindowOpaque(f,false);
        }
    
    }
    

    Note that you need to either have an undecorated window or one that is decorated by Java alone (not the default OS decoration) otherwise the code won't work.

    0 讨论(0)
  • 2021-01-03 08:39

    You could try using the Robot Class http://java.sun.com/javase/6/docs/api/java/awt/Robot.html which allows you to specify system events to the low level operating system, specifically things like mouse events.

    0 讨论(0)
  • 2021-01-03 08:40

    This is not answer, but an update which corrects dangerous issues to the accepted answer as well as providing an example compatible with Java 7+

    Per-Pixel alphering checks each pixel in the window to determine if it's transparent or not. If it's transparent, then the mouse events are allowed to pass through it, if its is not transparent, the mouse events will be caught by the window. This is generally an OS level issue.

    The example is you provide is actually doing some very dangerous things, first it's painting a translucent color onto a opaque component, this means that Swing doesn't know that it should actually be painting anything under the component and could also result in a number of very nasty paint artifacts, as Swing only knows about opaque and transparent component, it doesn't know about semi-transparent components, so you need to trick the API.

    When performing custom painting, you should always call super.paintComponent to ensure that the Graphics context is setup correctly before painting. In your case, you should also make the component transparent using setOpaque and passing it false

    import java.awt.AlphaComposite;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class TestFrame {
    
        public static void main(String[] args) {
            new TestFrame();
        }
    
        public TestFrame() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setUndecorated(true);
                    frame.setAlwaysOnTop(true);
                    frame.setBackground(new Color(0, 0, 0, 0));
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setOpaque(false);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setColor(Color.BLUE);
                g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
                g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
                g2d.dispose();
            }
    
        }
    
    }
    
    0 讨论(0)
  • 2021-01-03 08:41

    Savvas' answer helped me perfectly even on MacOS X 10.7.3 using Java 1.6.0_31. Thanks! The only thing: I additionally had to set

    f.setUndecorated(true);
    
    0 讨论(0)
提交回复
热议问题