Pass mouse events to applications behind from a Java UI

笑着哭i 提交于 2020-01-29 05:37:07

问题


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 can easily create a transparent Java UI using 6.0 but couldn't get any info about passing events through the app to any applications(say a browser) behind.


回答1:


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.




回答2:


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);



回答3:


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();
        }

    }

}



回答4:


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.



来源:https://stackoverflow.com/questions/1190168/pass-mouse-events-to-applications-behind-from-a-java-ui

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!