Victor2748
Victor2748

Reputation: 4199

How to pass events through a JFrame?

I have an undecorated JFrame with some contents on it (Labels, Images, etc.). I need the JFrame to pass all the events through it. For example: when a click is made on that JFrame, I want it to pass that click through, to the window/anything that is underneath the frame.

Problem Example:

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

Video Example of my goal: https://www.youtube.com/watch?v=irUQGDDSk_g

Similar question:

Pass mouse events to applications behind from a Java UI

Question: How can I make a JFrame with graphics, that will not catch the events from the user controlling, but to pass in through?

Upvotes: 1

Views: 1111

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347184

This is not an answer, but a correction to the code example

The example you provide is actually doing some very dangerous things, first it's painting a translucent color onto an 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, for example...

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

    }

}

Upvotes: 1

Related Questions