2011-09-17 29 views
11

En el modo de renderización pasiva, se pueden usar las interfaces KeyListener y ActionListener para manejar eventos del usuario.¿Cómo manejar eventos desde el teclado y el mouse en modo exclusivo de pantalla completa en Java?

¿Cuál es la forma correcta de manejo de eventos en modo de pantalla completa? Por favor extender este esqueleto que proporciona la implementación de clic del ratón y eventos de pulsación de teclas, por favor no hinchar tu ejemplo (el ejemplo se inicia el modo de pantalla completa exclusiva, usando un Timer para actualizar los gráficos en la ventana):

import java.applet.Applet; 
import java.awt.Color; 
import java.awt.DisplayMode; 
import java.awt.Graphics2D; 
import java.awt.GraphicsConfiguration; 
import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferStrategy; 
import javax.swing.JFrame; 
import javax.swing.Timer; 

public class applet extends Applet 
{ 
    Timer timer; 
    JFrame frame; 
    DisplayMode[] displayModes = new DisplayMode[] { 
      new DisplayMode(1280, 800, 32, 60) 
    }; 

    BufferStrategy bufferStrategy; 
    Rectangle bounds; 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 

    /** 
    * @param args 
    */ 

    public void init() 
    { 

     GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); //displays, fonts, color shemes... 
     GraphicsDevice device = env.getDefaultScreenDevice(); //for one-display systems 

     setIgnoreRepaint(true); 

     GraphicsConfiguration gc = device.getDefaultConfiguration(); 
     frame = new JFrame(gc); 

     device.setFullScreenWindow(frame); 

     if (device.isDisplayChangeSupported()) 
      device.setDisplayMode(displayModes[0]); 

     frame.createBufferStrategy(2); 
     bufferStrategy = frame.getBufferStrategy(); 

     timer = new Timer(1000/50, new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       Graphics2D g = null; 
       try { 
        g = (Graphics2D) bufferStrategy.getDrawGraphics(); 
        render(g); 
       } finally { 
        g.dispose(); 
       } 
       bufferStrategy.show(); 
      } 

     }); 

    } 

    private void render(Graphics2D g) { 
     g.setColor(Color.BLACK); 
     g.fillRect(0, 0, bounds.width, bounds.height); 
    } 

    public void start() 
    { 
     timer.start(); 

    } 

    public void stop() 
    { 
     timer.stop(); 
    } 

} 

Respuesta

22

Parece los enfoques habituales que se muestran en How to Use Key Bindings y How to Write a Mouse Listener funcionan correctamente en Full-Screen Exclusive Mode.

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.WindowEvent; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 

/** @see http://stackoverflow.com/questions/7456227 */ 
public class FullScreenTest extends JPanel { 

    private static final String EXIT = "Exit"; 
    private JFrame f = new JFrame("FullScreenTest"); 
    private Action exit = new AbstractAction(EXIT) { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       f.dispatchEvent(new WindowEvent(
        f, WindowEvent.WINDOW_CLOSING)); 
      } 
     }; 
    private JButton b = new JButton(exit); 

    public FullScreenTest() { 
     this.add(b); 
     f.getRootPane().setDefaultButton(b); 
     this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), EXIT); 
     this.getActionMap().put(EXIT, exit); 
     this.addMouseMotionListener(new MouseAdapter() { 

      @Override 
      public void mouseMoved(MouseEvent e) { 
       FullScreenTest.this.setToolTipText(
        "("+ e.getX() + "," + e.getY() + ")"); 
      } 
     }); 
    } 

    private void display() { 
     GraphicsEnvironment env = 
      GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     GraphicsDevice dev = env.getDefaultScreenDevice(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setBackground(Color.darkGray); 
     f.setResizable(false); 
     f.setUndecorated(true); 
     f.add(this); 
     f.pack(); 
     dev.setFullScreenWindow(f); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new FullScreenTest().display(); 
      } 
     }); 
    } 
} 
+0

¡Gracias por la respuesta! ¿Podría también proporcionar el mismo ejemplo, pero como applet de Java? Quería que el ejemplo fuera un applet de Java, pero parece que olvidé incluir eso en la primera publicación ... Creo que solo necesitas hacer pequeñas adiciones/cambios en el código que proporcionaste, te lo agradeceré mucho si lo haces , porque tu ejemplo es muy bueno para estudiar! – Vadim

+2

Sugeriría 'JApplet', pero probablemente tendría que estar [signed] (http://download.oracle.com/javase/tutorial/deployment/applet/security.html) por seguridad. Puede probarlo utilizando un enfoque híbrido que se muestra [aquí] (https://sites.google.com/site/drjohnbmatthews/subway); [tag: java-web-start] sería una mejor estrategia de implementación. – trashgod

+0

¡Gracias, lo revisaré! – Vadim

7

Como se sugiere here, los usuarios de Mac OS X pueden tener diferentes expectativas de los usuarios de aplicaciones de pantalla completa. Un enfoque alternativo, que se muestra here, se basa en las clases com.apple.eawt que "proporcionan una forma sencilla de implementar características nativas para ajustar con precisión las aplicaciones Java en Mac OS X". El método FullScreenUtilitiessetWindowCanFullScreen() habilita la función y el método ApplicationrequestToggleFullScreen() cambia la configuración de forma dinámica. Tenga en cuenta cómo el ícono expandir es diferente entre versions.

Mac OS 10.9, Mavericks:

10.9

Mac OS 10.10, Yosemite:

10.10

Mac OS X 10.11, El Capitán:

enter image description here

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 

/** 
* @see https://stackoverflow.com/a/30308671/230513 
* @see https://stackoverflow.com/questions/7456227 
* @see https://stackoverflow.com/q/13064607/230513 
* @see https://stackoverflow.com/q/30089804/230513 
* @see https://stackoverflow.com/q/25270465/230513 
* @see http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/macosx/classes/com/apple/ 
*/ 
public class FullScreenTest extends JPanel { 

    private static final String NAME = "Mac OS X Full Screen Test"; 
    private static final String TOGGLE = "Toggle Full Screen"; 
    private final JFrame f = new JFrame(NAME); 
    private final Action exit = new AbstractAction(TOGGLE) { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      toggleOSXFullscreen(f); 
     } 
    }; 
    private final JButton b = new JButton(exit); 

    public FullScreenTest() { 
     this.add(b); 
     f.getRootPane().setDefaultButton(b); 
     this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), TOGGLE); 
     this.getActionMap().put(TOGGLE, exit); 
     this.addMouseMotionListener(new MouseAdapter() { 

      @Override 
      public void mouseMoved(MouseEvent e) { 
       FullScreenTest.this.setToolTipText(
         "(" + e.getX() + "," + e.getY() + ")"); 
      } 
     }); 
    } 

    private void display() { 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setBackground(Color.darkGray); 
     f.add(this); 
     f.add(new JLabel(NAME, JLabel.CENTER), BorderLayout.SOUTH); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
     if (System.getProperty("os.name").startsWith("Mac OS X")) { 
      enableOSXFullscreen(f); 
      toggleOSXFullscreen(f); 
      enableOSXQuitStrategy(); 
     } 
     f.addWindowListener(new WindowAdapter() { 

      @Override 
      public void windowClosing(WindowEvent e) { 
       System.out.println(e); 
      } 
     }); 
    } 

    //FullScreenUtilities.setWindowCanFullScreen(window, true); 
    private void enableOSXFullscreen(Window window) { 
     try { 
      Class util = Class.forName("com.apple.eawt.FullScreenUtilities"); 
      Class params[] = new Class[]{Window.class, Boolean.TYPE}; 
      Method method = util.getMethod("setWindowCanFullScreen", params); 
      method.invoke(util, window, true); 
     } catch (ClassNotFoundException | NoSuchMethodException | 
       SecurityException | IllegalAccessException | 
       IllegalArgumentException | InvocationTargetException exp) { 
      exp.printStackTrace(System.err); 
     } 
    } 

    //Application.getApplication().requestToggleFullScreen(window); 
    private void toggleOSXFullscreen(Window window) { 
     try { 
      Class application = Class.forName("com.apple.eawt.Application"); 
      Method getApplication = application.getMethod("getApplication"); 
      Object instance = getApplication.invoke(application); 
      Method method = application.getMethod("requestToggleFullScreen", Window.class); 
      method.invoke(instance, window); 
     } catch (ClassNotFoundException | NoSuchMethodException | 
       SecurityException | IllegalAccessException | 
       IllegalArgumentException | InvocationTargetException exp) { 
      exp.printStackTrace(System.err); 
     } 
    } 

    //Application.getApplication().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS); 
    private void enableOSXQuitStrategy() { 
     try { 
      Class application = Class.forName("com.apple.eawt.Application"); 
      Method getApplication = application.getMethod("getApplication"); 
      Object instance = getApplication.invoke(application); 
      Class strategy = Class.forName("com.apple.eawt.QuitStrategy"); 
      Enum closeAllWindows = Enum.valueOf(strategy, "CLOSE_ALL_WINDOWS"); 
      Method method = application.getMethod("setQuitStrategy", strategy); 
      method.invoke(instance, closeAllWindows); 
     } catch (ClassNotFoundException | NoSuchMethodException | 
       SecurityException | IllegalAccessException | 
       IllegalArgumentException | InvocationTargetException exp) { 
      exp.printStackTrace(System.err); 
     } 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new FullScreenTest()::display); 
    } 
} 
+0

Consulte también [* Swing en OSX: comando de captura de trampa-Q? *] (Http://stackoverflow.com/q/2061194/230513) – trashgod

+0

Nota rápida: la llamada a 'requestToggleFullScreen' parece fallar silenciosamente si se realiza antes de que el recuadro sea [visualizable] (https://docs.oracle.com/javase/8/docs/api/java/awt/Component.html#isDisplayable--). (Pruebas en El Capitán 10.11.6.) – Radiodef

Cuestiones relacionadas