0

My Java app uses two JFrames - the first one to present a choice to the user from a limited number of options (no full screen), and the second to present the data (with the full screen option).

I was using setVisible() to switch between my two frames which was good because it reused the previous Virtual Desktop and retained the full screen mode, but I had to switch to dispose() in order to hide the second JFrame because of a toolkit thread paint problem.

When I go into full screen mode in frame2, a new virtual desktop is created - but if I dispose frame2, that VD still exists as an empty grey desktop. Having disposed() it to return to frame1, if I then switch back again to frame2 we are no longer in full screen... and if I do... then I now have 2 virtual desktops. And so on.

Using setVisible(false) on frame2 also leaves the empty virtual desktop in place, although that is less of a problem than the repaint/buffer issue, as the next time I setVisible(true) on frame2 at least it opens up in the same VD, as I mentioned above.

My question is: can I save and restore the full screen mode in frame2 using the same VD after a dispose(), or can I at least force the VD to close? Or have I missed another solution to the problem? Or is this simply because I'm not strict following Apple's full screen guidelines?!

Thank you in advance for any help.

UPDATE: I went back to using setVisible(false) to hide frame2, but using new() each time I display it (to avoid repaint/buffer problem), and again I have the same duplicate VD problem. I also implemented com.apple.eawt.Application.requestToggleFullScreen along with com.apple.eawt.FullScreenListener to quit full screen before I dispose, but the app hangs. Now looks like I'll have to live with the repaint.buffer issue to allow full screen switching to work correctly.

SSCCE:

import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class SwingFramesFullScreenMacDemo extends javax.swing.JFrame {

    JFrame secondFrame;
    JPanel myPanel;

    public SwingFramesFullScreenMacDemo() {

        //Setup UI With Button to show secondFrame
        JPanel thisPanel = new JPanel();
        JButton jbtOpenFullScreenFrame = new JButton("Open Full Screen Frame");
        jbtOpenFullScreenFrame.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                secondFrame.setVisible(true);
                setVisible(false);
            }
        });

        thisPanel.add(jbtOpenFullScreenFrame);
        this.add(thisPanel);
        this.pack();

        // Setup Second Frame With Full Screen Support
        secondFrame = new JFrame();

        myPanel = new JPanel();

        //Dispose() works without residual image, but leaves open virtual desktop for each time
        //you go to full screen then dispose
        JButton jbtDispose = new JButton("Dispose");

        jbtDispose.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                setVisible(true);
                secondFrame.dispose();

            }
        });

        //SetVisible(false) gives residual image on reopening second frame despite clearing colour
        //works well for fullscreen, only one virtual desktop open for lifetime of app
        JButton jbtSetVisibleFalse = new JButton("Set Visible to False");

        jbtSetVisibleFalse.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                secondFrame.setVisible(false);
                setVisible(true);

            }
        });

        myPanel.add(jbtDispose);
        myPanel.add(jbtSetVisibleFalse);

        secondFrame.add(myPanel);
        secondFrame.pack();

        enableFullScreenMode(secondFrame);

        secondFrame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosed(WindowEvent e) {
                setVisible(true);
                secondFrame.setVisible(false);

            }
        });

    }

    public static void enableFullScreenMode(Window window) {

        String methodName = "setWindowCanFullScreen";

        try {
            Class<?> clazz = Class.forName(com.apple.eawt.FullScreenUtilities.class.getName());
            Method method = clazz.getMethod(methodName, new Class<?>[]{
                Window.class, boolean.class});
            method.invoke(null, window, true);
        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException t) {
            System.err.println("Full screen mode is not supported");
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                javax.swing.JFrame fullScreenMacProblem = new SwingFramesFullScreenMacDemo();
                fullScreenMacProblem.addWindowListener(new java.awt.event.WindowAdapter() {
                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {

                        System.exit(0);
                    }
                });

                fullScreenMacProblem.setVisible(true);

            }
        });

    }

}
Community
  • 1
  • 1
jazzwhistle
  • 337
  • 2
  • 12
  • See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/a/9554657/418556) – Andrew Thompson Feb 03 '14 at 23:23
  • 1
    Shouldn't you be un-full screen the window before you dispose of it? – MadProgrammer Feb 03 '14 at 23:51
  • More [here](http://stackoverflow.com/q/20053223/230513). – trashgod Feb 04 '14 at 02:30
  • @AndrewThompson I did indeed read that earlier, and the rebuttal... In fact you don't get 2 icons in the dock as he suggests, and his other solutions just won't work for my app, so I'm stuck with 2 JFrames for the moment at least, and everything works perfectly apart from the virtual desktop issue. – jazzwhistle Feb 04 '14 at 08:24
  • @MadProgrammer I'll try that now, thanks - I found how to toggle full screen, but not yet how to detect it... – jazzwhistle Feb 04 '14 at 08:26

1 Answers1

0

My solution to this "catch 22" is to only instantiate frame2 once in frame1, to use dispose() when frame2 is not full screen (avoids repaint/buffer issue), and to use setVisible(false) when frame2 is fullscreen (maintains a single virtual desktop for frame2). Since the repaint issue does not affect full screen views this works very well, although I'm sure the purists will baulk!

jazzwhistle
  • 337
  • 2
  • 12