JWebBrowser (extends JPanel) Showing Above Glass Pane

2.3k views Asked by At

I am using the DJ Native Swing API to be able to use JWebBrowser.

public class GUI extends JPanel {

    Robot robot;
    JComponent glassPane;

    public GUI(final Bot bot) {
        super(new BorderLayout());
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
        JPanel webBrowserPanel = new JPanel(new BorderLayout());
        JWebBrowser webBrowser = new JWebBrowser(JWebBrowser.constrainVisibility());
        webBrowser.setBarsVisible(false);
        webBrowser.setButtonBarVisible(false);
        webBrowser.setMenuBarVisible(false);
        webBrowser.navigate("http://google.com");
        webBrowserPanel.add(webBrowser, BorderLayout.CENTER);
        add(webBrowserPanel, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 4, 4));
        final JButton button = new JButton("Start");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (bot.isRunning()) {
                    button.setText("Start");
                } else {
                    button.setText("Stop");
                }
                bot.setRunning(!bot.isRunning());
            }
        });
        buttonPanel.add(button, BorderLayout.WEST);
        add(buttonPanel, BorderLayout.NORTH);

        JFrame mainFrame = new JFrame("Bot");
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.getContentPane().add(this, BorderLayout.CENTER);

        glassPane = new JComponent()
        {
            public void paintComponent(Graphics g)
            {
                g.setColor(new Color(1, 0, 0, 0.5f));
                g.fillRect(10, 10, 815, 775);
            }
        };
        glassPane.setSize(815,775);
        glassPane.setOpaque(false);
       mainFrame.setGlassPane(glassPane);
        glassPane.setVisible(true);


        mainFrame.setSize(815, 775);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible(true);
    }
}

When I run this, I expect to see a red rectangle over the whole GUI. This is not what happens. This is what I see (sorry, it won't let me post direct images): https://i.stack.imgur.com/ZAe51.png

Why is the JWebBrowser appearing over the glass pane? I thought the Glass Pane should be over EVERYTHING.

JWebBrowser extends JPanel. Here is the documentation: Javadoc

My goal for this glass pane is to be able to get the mouse position when the user is using the GUI. For some reason the mouse position is returning null (even though it is over the component) using webBrowser.getMousePosition() or webBrowserPanel.getMousePosition().

2

There are 2 answers

10
mKorbel On

Why is the JWebBrowser appearing over the glass pane? I thought the Glass Pane should be over EVERYTHING.

because you set mainFrame.setGlassPane(glassPane);

My goal for this glass pane is to be able to get the mouse position when the user is using the GUI. For some reason the mouse position is returning null (even though it is over the component) using webBrowser.getMousePosition() or webBrowserPanel.getMousePosition().

GlassPane by default to consume MouseEvents, but you can redispatch those events

EDIT

if I use code example from codersource

import java.awt.Image;
import java.awt.Toolkit;
import java.util.Arrays;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import chrriis.common.UIUtils;
import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import javax.swing.JRootPane;

/**
 * @author Christopher Deckers
 */
public class DemoFrame {

    public static void main(String[] args) {
        UIUtils.setPreferredLookAndFeel();
        NativeInterface.open();
        Toolkit.getDefaultToolkit().setDynamicLayout(true);
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                JFrame demoFrame = new JFrame("The DJ Project - NativeSwing (SWT)");
                Class<DemoFrame> clazz = DemoFrame.class;
                if (System.getProperty("java.version").compareTo("1.6") >= 0) {
                    demoFrame.setIconImages(Arrays.asList(new Image[]{
                                new ImageIcon(clazz.getResource("resource/DJIcon16x16.png")).getImage(),
                                new ImageIcon(clazz.getResource("resource/DJIcon24x24.png")).getImage(),
                                new ImageIcon(clazz.getResource("resource/DJIcon32x32.png")).getImage(),
                                new ImageIcon(clazz.getResource("resource/DJIcon48x48.png")).getImage(),
                                new ImageIcon(clazz.getResource("resource/DJIcon256x256.png")).getImage(),}));
                } else {
                    demoFrame.setIconImage(new ImageIcon(clazz.getResource("resource/DJIcon32x32Plain.png")).getImage());
                }
                demoFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                demoFrame.getContentPane().add(new DemoPane());
                demoFrame.setSize(800, 600);
                demoFrame.setLocationByPlatform(true);


                MyGlassPane glassPane = new MyGlassPane();
                JRootPane rootPane = SwingUtilities.getRootPane(demoFrame);
                rootPane.setGlassPane(glassPane);
                glassPane.activate("");


                demoFrame.setVisible(true);
            }
        });
        NativeInterface.runEventPump();
    }
}

with code by @camickr

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;

/*
 *  Simple implementation of a Glass Pane that will capture and ignore all
 *  events as well paint the glass pane to give the frame a "disabled" look.
 *
 *  The background color of the glass pane should use a color with an
 *  alpha value to create the disabled look.
 */
public class MyGlassPane extends JComponent
        implements KeyListener {

    private final static Border MESSAGE_BORDER = new EmptyBorder(10, 10, 10, 10);
    private JLabel message = new JLabel();

    public MyGlassPane() {
        //  Set glass pane properties

        setOpaque(false);
        Color base = UIManager.getColor("inactiveCaptionBorder");
        Color background = new Color(base.getRed(), base.getGreen(), base.getBlue(), 128);
        setBackground(background);
        setLayout(new GridBagLayout());

        //  Add a message label to the glass pane

        add(message, new GridBagConstraints());
        message.setOpaque(true);
        message.setBorder(MESSAGE_BORDER);

        //  Disable Mouse, Key and Focus events for the glass pane

        addMouseListener(new MouseAdapter() {
        });
        addMouseMotionListener(new MouseMotionAdapter() {
        });

        addKeyListener(this);

        setFocusTraversalKeysEnabled(false);
    }

    /*
     *  The component is transparent but we want to paint the background
     *  to give it the disabled look.
     */
    @Override
    protected void paintComponent(Graphics g) {
        g.setColor(getBackground());
        g.fillRect(0, 0, getSize().width, getSize().height);
    }

    /*
     *  The background color of the message label will be the same as the
     *  background of the glass pane without the alpha value
     */
    @Override
    public void setBackground(Color background) {
        super.setBackground(background);

        Color messageBackground = new Color(background.getRGB());
        message.setBackground(messageBackground);
    }
//
//  Implement the KeyListener to consume events
//

    public void keyPressed(KeyEvent e) {
        e.consume();
    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
        e.consume();
    }

    /*
     *  Make the glass pane visible and change the cursor to the wait cursor
     *
     *  A message can be displayed and it will be centered on the frame.
     */
    public void activate(String text) {
        if (text != null && text.length() > 0) {
            message.setVisible(true);
            message.setText(text);
            message.setForeground(getForeground());
        } else {
            message.setVisible(false);
        }

        setVisible(true);
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        requestFocusInWindow();
    }

    /*
     *  Hide the glass pane and restore the cursor
     */
    public void deactivate() {
        setCursor(null);
        setVisible(false);
    }
}

then output will be

enter image description here

than I can't agreed that GlassPane is bellow any of JComponent, nor JWebBrowser, story ended,

EDIT Correction, I can't found an alternative (right alternative) for GlassPane for SWT, then you are right JWebBrowser is over the AWT / Swing GlassPane

output will be

enter image description here

3
Christopher Deckers On

JWebBrowser is a heavyweight component. DJ Native Swing simplifies that integration in Swing by applying all sorts of clipping rules but it cannot do alpha blending.

The closest you can achieve would be to do what the demo application shows in "Additional Features > Pseudo Transparency". Unfortunately, it seems on Windows 7 there is a flashing effect for every refresh but this may not be an issue in your case if you do not refresh often.