How to make a JDialog work on a JFrame that is fullscreen

83 Views Asked by At

I'm writing a program using Swing and AWT and I have a JFrame that is fullscreen. On said frame I have a button that opens a JDialog on that frame. When I click the button it does create the jDialog but it makes my screen look like it's having a siezure. Please help. Is there any way to make a popup menu that does the equivilent of grab_set(), does not move, and can hold objects?

Code for fullscreen

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

//
public class test   {
   public static void main(String[] args)
   {
      GraphicsEnvironment graphics = GraphicsEnvironment.getLocalGraphicsEnvironment();
      GraphicsDevice device = graphics.getDefaultScreenDevice();
      
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      
      f.setUndecorated(true);
      f.setResizable(false);
      JMenuBar mb = new JMenuBar();
      mb.setLayout(new BorderLayout());
      
      JButton x = new JButton("X");
      Listeners close_button= new Listeners();
      x.addActionListener(close_button.close());
      x.setPreferredSize(new Dimension(30,30));
      mb.add(x, BorderLayout.EAST);
      f.setJMenuBar(mb);
      device.setFullScreenWindow(f);
   }
}

Listener Code

public class Listeners
{
private class Listener_popup implements ActionListener
   {
    private Frame frame;
    public Listener_popup(Frame f)
    {
     frame=f;
    }
    public void actionPerformed(ActionEvent e)
    {
     JDialog d= new JDialog(frame,"hello");
     JLabel l=new JLabel("Hello");
     d.add(l);
     d.setSize(100,100);
     d.setUndecorated(true);
     d.setVisible(true);
    }
   }
  }

I tried using a jButton with action listeners to create a jDialog and I looked into jPopup but it wasn't quite what I was looking for. Open to any suggestions.

1

There are 1 best solutions below

2
MadProgrammer On

I find it kind of weird that you're trying to display another window while your app is in "full screen exclusive" mode, the point is to give you window "exclusive" access to the screen device.

When I tried to display a JOptionPane on MacOS, nothing happened, but then I couldn't interact with the window, because the dialog had modal access :/.

You could "fake" it though. JOptionPane is, after all, just a component.

The following example makes use of the of the windows glassPane to present a customised JOptionPane...

import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
                device.setFullScreenWindow(frame);
//                device.setDisplayMode(new DisplayMode(800, 600, 32, 60));
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            JButton btn = new JButton("Hello");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JOptionPane optionPane = new JOptionPane("This is a test", JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION);
                    optionPane.addPropertyChangeListener(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            String propertyName = evt.getPropertyName();
                            if (JOptionPane.VALUE_PROPERTY.equals(propertyName)) {
                                Container parent = optionPane.getParent();
                                parent.remove(optionPane);
                                parent.revalidate();
                                parent.repaint();
                            }
                        }
                    });

                    optionPane.setBorder(
                            new CompoundBorder(
                                    new LineBorder(Color.DARK_GRAY, 8),
                                    new EmptyBorder(8, 8, 8, 8)
                            )
                    );

                    JRootPane rootPane = SwingUtilities.getRootPane(TestPane.this);
                    JComponent glassPane = (JComponent) rootPane.getGlassPane();

                    glassPane.setLayout(new GridBagLayout());
                    glassPane.add(optionPane);
                    glassPane.setVisible(true);
                }
            });
            add(btn);
        }

    }

}

Now, of you attached a MouseListener and KeyListener to the glassPane you could effectively "consume" all of those events, making the dialog "appear" modal.