2

In my program I have method to toggle between normal windows and fullscreen state:

public void setFullScreen(boolean enableFullScreen) {
    Frame.fullScreen = enableFullScreen;
    dispose();
    if ( enableFullScreen ) {
        getContentPane().setPreferredSize(resFull);
        setSize(resFull);
        setBounds(Frame.graphicsDev.getConfigurations()[0].getBounds().x, Frame.graphicsDev.getConfigurations()[0].getBounds().y, resFull.width, resFull.height);
        //code for resizing components
        setUndecorated(true);
        setResizable(false);
    } else {
        getContentPane().setSize(resNormal);
        getContentPane().setPreferredSize(resNormal);
        //code for resizing components
        setUndecorated(false);
        setResizable(true);
    }
    pack();
    setVisible(true);
}

The resFull and resNormal are Dimension variables.

When I click F11 in opened normal window it changes fullScreen state (setFullScreen(!Frame.fullScreen)), but after change it usually doesn't recieve any signals - I have to switch to other application and then turn back to this window - then it works.

  • 2
    What are you disposing and why dispose it? Dispose is for deleting whatever you call it on. – Radiodef Oct 28 '13 at 21:22
  • 1
    @Radiodef: actually dispose is not for "deleting" but for releasing native resources. You definitely do not want to dispose a top-level window before showing it, but calling `pack()` and `setVisible(true)` should re-constitute native resources. – Hovercraft Full Of Eels Oct 28 '13 at 21:25
  • I had to do it, because I wanted to call `setUndecorated()`. – Marek Pikuła Oct 28 '13 at 21:25
  • I forgot to add, that this method is in Frame class. – Marek Pikuła Oct 28 '13 at 21:26
  • MarPiRK: I've not heard of this requirement for creating an undecorated window, but I usually don't create these either. Regardless, you may have a focus issue since KeyListeners require that they listen to a focused component. Myself, I try to avoid use of KeyListeners and try to favor use of Key Bindings. – Hovercraft Full Of Eels Oct 28 '13 at 21:27
  • `"I forgot to add, that this method is in Frame class."` -- do you mean a class that extends `JFrame`, not Frame? – Hovercraft Full Of Eels Oct 28 '13 at 21:27
  • [About setUndecorated()](http://stackoverflow.com/questions/875132/how-to-call-setundecorated-after-a-frame-is-made-visible?rq=1) Is it possible to force focus on that frame? – Marek Pikuła Oct 28 '13 at 21:28
  • @HovercraftFullOfEels Yeah but in a word "deleting" is what it ultimately does. If the underlying GUI is C++ then I'd imagine literally the delete operator is used. Though I was not aware the resources could be reinstated. – Radiodef Oct 28 '13 at 21:29
  • @Hovercraft Full Of Eels Yes, it extends JFrame – Marek Pikuła Oct 28 '13 at 21:30
  • @Radiodef: no, you're wrong. Look at the Window API which is where the code originates from. It does not delete any objects or any logical components. All it does is release system resources, and that's it. So a JFrame and all of its components still exist and nothing is GC'd as long as it has a viable reference, but the Operating System window resource *is* released, that's it. If the top-level window is re-rendered by calling `pack()` or `setVisible(true)` its prior state is reinstated. – Hovercraft Full Of Eels Oct 28 '13 at 21:31
  • @MarPiRK: consider creating and posting an [sscce](http://sscce.org) that we can compile, run and test. – Hovercraft Full Of Eels Oct 28 '13 at 21:41
  • @HovercraftFullOfEels Guess I am wrong. I've never heard of the dispose requirement until now either although the doc for setUndecorated specifies that it can only be called if the window is not displayable. The isDisplayable method specifies that dispose is a way to do this: http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#isDisplayable() So it appears that is the correct way to do this. – Radiodef Oct 28 '13 at 21:50

1 Answers1

0

Likely your problem is due to the JButton stealing the focus when it is pressed, causing your KeyListener to be listening to an unfocused component. Again a solution is to use key bindings.

My sscce as proof that both KeyListeners and Key Bindings by themselves work fine after the transformation that you're trying to achieve:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.*;

import javax.swing.*;

@SuppressWarnings("serial")
public class TestUndecoratedKeyListener {
   protected static final int PREF_W = 400;
   protected static final int PREF_H = PREF_W;

   private static void createAndShowGui() {
      final JFrame frame = new JFrame("TestUndecoratedKeyListener");

      final JPanel mainPanel = new JPanel() {
         @Override
         public Dimension getPreferredSize() {
            return new Dimension(PREF_W, PREF_H);
         }
      };

      JToggleButton toggleButton = new JToggleButton("Full Screen");
      toggleButton.setFocusable(false);
      toggleButton.setMnemonic(KeyEvent.VK_F);
      toggleButton.addItemListener(new ItemListener() {

         @Override
         public void itemStateChanged(ItemEvent e) {
            if (e.getStateChange() == ItemEvent.SELECTED) {
               frame.dispose();
               frame.setUndecorated(true);
               frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
               frame.setVisible(true);
            } else {
               frame.dispose();
               frame.setUndecorated(false);
               frame.setExtendedState(JFrame.NORMAL);
               frame.pack();
               frame.setLocationRelativeTo(null);
               frame.setVisible(true);
            }
         }
      });
      mainPanel.add(toggleButton);
      final JLabel keyListenerLabel = new JLabel();
      final JLabel keyBindingLabel = new JLabel();

      mainPanel.add(new JLabel("Press Right or Left Arrow Key To Test"));
      mainPanel.add(keyListenerLabel);
      mainPanel.add(keyBindingLabel);

      keyListenerLabel.setBorder(BorderFactory.createLineBorder(Color.black));
      keyBindingLabel.setBorder(BorderFactory.createLineBorder(Color.black));

      mainPanel.addKeyListener(new KeyAdapter() {

         @Override
         public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_LEFT) {
               keyListenerLabel.setText("KeyListener: left pressed");
            } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
               keyListenerLabel.setText("KeyListener: right pressed");
            }
         }
      });

      int condition = JPanel.WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = mainPanel.getInputMap(condition);
      ActionMap actionMap = mainPanel.getActionMap();

      KeyStroke leftArrowStroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
      KeyStroke rightArrowStroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);
      inputMap.put(leftArrowStroke, leftArrowStroke.toString());
      inputMap.put(rightArrowStroke, rightArrowStroke.toString());
      actionMap.put(leftArrowStroke.toString(), new AbstractAction() {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            keyBindingLabel.setText("Key Bindings: left Arrow Pressed");
         }
      });
      actionMap.put(rightArrowStroke.toString(), new AbstractAction() {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            keyBindingLabel.setText("Key Bindings: right Arrow Pressed");
         }
      });


      mainPanel.setFocusable(true);
      mainPanel.requestFocusInWindow();

      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373