سؤال

I'm trying to make a JPanel go full screen when you click a button, and back again when you press escape.

I've managed to get the window to go full screen, but because of the whole thing about adding components removing them from other containers, I end up with a blank JPanel.

I chose to make a separate JFrame to render full screen, the class of which is as follows (note that this is an inner class, so myPanel refers to a panel that already exists in MyJFrame):

public class FullScreen extends JFrame {

    private static final long serialVersionUID = 1L;

    private GraphicsDevice device;

    private boolean isFullScreen;

    public FullScreen() {
        this.setContentPane(myPanel);
        this.setUndecorated(true);

        // Fullscreen return
        this.addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(KeyEvent e) {
                // Exit fullscreen when ESC pressed
                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    exitFullScreen();
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
            }

            @Override
            public void keyTyped(KeyEvent e) {
            }
        });
    }

    public void enterFullScreen() {
        if (!isFullScreen) {
            // Get the current device
            GraphicsEnvironment graphicsEnvironment = 
                    GraphicsEnvironment.getLocalGraphicsEnvironment();
            device = graphicsEnvironment.getDefaultScreenDevice();

            if (device.isFullScreenSupported()) {
                // Make the current window invisible
                MyJFrame.this.setVisible(false);
                // Set the full screen window
                device.setFullScreenWindow(this);
                isFullScreen = true;
            }
        }
    }

    public void exitFullScreen() {
        if (isFullScreen) {
            // Reset the full screen window
            device.setFullScreenWindow(null);
            MyJFrame.this.setVisible(true);
            isFullScreen = false;
        }
    }
}

Any other bright ideas on how to accomplish this?

هل كانت مفيدة؟

المحلول 3

Here's my class built into an example that works very nicely. I'm sure I'm not disposing and validating the frame properly so please comment on it so I can update it.

public class FullScreenExample extends JFrame {

    public class FullScreen {
        private GraphicsDevice device;
        private JFrame frame;
        private boolean isFullScreen;

        public FullScreen() {
            frame = new JFrame();
            JPanel content = new JPanel();
            content.setLayout(new BorderLayout());
            frame.setContentPane(content);
            frame.setUndecorated(true);

            // Full screen escape
            frame.addKeyListener(new KeyListener() {
                @Override
                public void keyPressed(KeyEvent e) {
                    // Exit full screen when ESC pressed
                    if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                        exitFullScreen();
                    }
                }

                @Override
                public void keyReleased(KeyEvent e) {}

                @Override
                public void keyTyped(KeyEvent e) {}
            });
        }

        public void enterFullScreen() {
            if (!isFullScreen) {
                // Get the current device
                GraphicsConfiguration config = FullScreenExample.this.getGraphicsConfiguration();
                device = config.getDevice();

                // Remove the panel from the wrapper
                myWrapper.remove(myPanel);
                // Add the panel to the full screen frame
                frame.getContentPane().add(myPanel);
                // Set the full screen window
                device.setFullScreenWindow(frame);
                isFullScreen = true;
            }
        }

        public void exitFullScreen() {
            if (isFullScreen) {
                // Remove the fractal from the full screen frame
                frame.getContentPane().remove(myPanel);
                // Add the panel back to the wrapper
                myWrapper.add(myPanel);
                // Disable full screen
                device.setFullScreenWindow(null);
                // Dispose frame
                frame.dispose();
                // Revalidate window
                FullScreenExample.this.validate();
                isFullScreen = false;
            }
        }
    }

    /*
     * This example uses a main content panel, myPanel
     * and a wrapper to host the panel in the main JFrame, myWrapper.
     */
    private JPanel myPanel, myWrapper;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                FullScreenExample frame = new FullScreenExample();
                frame.init();
                frame.setVisible(true);
            }
        });
    }

    public void init() {
        // Generate example main window
        JPanel content = new JPanel();
        content.setBorder(new EmptyBorder(5, 5, 5, 5));
        content.setLayout(new BorderLayout());
        this.setContentPane(content);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        myPanel = new JPanel();
        myPanel.setBackground(Color.BLUE);

        // Full screen button and listener
        JButton fullscreen = new JButton("Full Screen");
        final FullScreen fs = new FullScreen();
        fullscreen.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                fs.enterFullScreen();
            }
        });

        myWrapper = new JPanel();
        myWrapper.setLayout(new BorderLayout());
        myWrapper.add(myPanel);

        content.add(myWrapper, BorderLayout.CENTER);
        content.add(fullscreen, BorderLayout.SOUTH);
        this.setBounds(100, 100, 350, 350);
    }
}

نصائح أخرى

Something like this seems to do it alright (to be improved and adapted):

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

class TestFullScreenPanel {

    private static class FSPanel implements ActionListener {
        private JPanel panel;
        private JButton button;
        private boolean fullScreen = false;
        private Container previousContentPane;

        public FSPanel(String label) {
            panel = new JPanel(new BorderLayout());
            button = new JButton(label);
            button.addActionListener(this);
            panel.add(button);
        }

        public JComponent getComponent() {
            return panel;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (!fullScreen) {
                goFullScreen();
            } else {
                ungoFullScreen();
            }
        }

        private void goFullScreen() {
            Window w = SwingUtilities.windowForComponent(button);
            if (w instanceof JFrame) {
                JFrame frame = (JFrame) w;
                frame.dispose();
                frame.setUndecorated(true);
                frame.getGraphicsConfiguration().getDevice().setFullScreenWindow(w);
                previousContentPane = frame.getContentPane();
                frame.setContentPane(button);
                frame.revalidate();
                frame.repaint();
                frame.setVisible(true);
                fullScreen = true;
            }
        }

        private void ungoFullScreen() {
            Window w = SwingUtilities.windowForComponent(button);
            if (w instanceof JFrame) {
                JFrame frame = (JFrame) w;
                frame.dispose();
                frame.setUndecorated(false);
                frame.getGraphicsConfiguration().getDevice().setFullScreenWindow(null);
                frame.setContentPane(previousContentPane);
                panel.add(button);
                frame.revalidate();
                frame.repaint();
                frame.setVisible(true);
                fullScreen = false;
            }
        }
    }

    TestFullScreenPanel() {
        final JFrame f = new JFrame(TestFullScreenPanel.class.getSimpleName());
        f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        f.add(new FSPanel("Center").getComponent(), BorderLayout.CENTER);
        f.add(new FSPanel("North").getComponent(), BorderLayout.NORTH);
        f.add(new FSPanel("South").getComponent(), BorderLayout.SOUTH);
        f.add(new FSPanel("West").getComponent(), BorderLayout.WEST);
        f.add(new FSPanel("East").getComponent(), BorderLayout.EAST);
        f.setSize(800, 600);
        f.setLocationByPlatform(true);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        // start the GUI on the EDT
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestFullScreenPanel();
            }
        });
    }
}

PS: disposal of the JFrame is only there to change the setUndecorated state.

.

import java.awt.Dimension;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class FullScreen {

    private static final long serialVersionUID = 1L;
    private GraphicsDevice device;
    private JButton button = new JButton("Close Meeee");
    private JPanel myPanel = new JPanel();
    private JFrame frame = new JFrame();

    public FullScreen() {
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        myPanel.setFocusable(true);
        myPanel.add(button);
        frame.add(myPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setUndecorated(true);
        frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke("ENTER"), "clickENTER");
        frame.getRootPane().getActionMap().put("clickENTER", new AbstractAction() {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                exitFullScreen();
            }
        });
        enterFullScreen();
        frame.setVisible(true);

        // code line for @MOD 
        // from http://stackoverflow.com/questions/15152297/how-to-get-extendedstate-width-of-jframe

        Runnable doRun = new Runnable() {
            @Override
            public void run() {
                System.out.println(frame.getBounds());
            }
        };
        SwingUtilities.invokeLater(doRun);
    }

    private void enterFullScreen() {
        GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
        device = graphicsEnvironment.getDefaultScreenDevice();
        if (device.isFullScreenSupported()) {
            device.setFullScreenWindow(frame);
            frame.validate();
        }
    }

    private void exitFullScreen() {
        device.setFullScreenWindow(null);
        myPanel.setPreferredSize(new Dimension(400, 300));
        frame.pack();
    }

    public static void main(String[] args) {
        Runnable doRun = new Runnable() {
            @Override
            public void run() {
                FullScreen fullScreen = new FullScreen();
            }
        };
        SwingUtilities.invokeLater(doRun);
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top