How to Handle Events from Keyboard and Mouse in Full Screen Exclusive Mode in Java

How to handle events from keyboard and mouse in full screen exclusive mode in java?

It looks like the usual approaches shown in How to Use Key Bindings and How to Write a Mouse Listener work correctly in 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();
}
});
}
}

Full Screen Exclusive Mode Key Input with just a Window

Example using Key Bindings. Really simple, also demonstrates the use of DisplayMode if you're so inclined, but once it's running, simply press and hold space, it will update, release it, it will update. Double click to close ;)

import java.awt.DisplayMode;
import java.awt.FontMetrics;
import java.awt.Graphics;
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.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class Test {

public static void main(String[] args) {
JFrame f = new JFrame("Test");
f.setUndecorated(true);
f.add(new TestPane());
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

GraphicsDevice device = GraphicsEnvironment
.getLocalGraphicsEnvironment().getDefaultScreenDevice();
if (device.isFullScreenSupported()) {
device.setFullScreenWindow(f);
if (device.isDisplayChangeSupported()) {
try {
List<DisplayMode> matchingModes = new ArrayList<>(25);

DisplayMode[] modes = device.getDisplayModes();
for (DisplayMode mode : modes) {
if (mode.getWidth() == 1280 && mode.getHeight() == 720) {
matchingModes.add(mode);
}
}

if (!matchingModes.isEmpty()) {
for (DisplayMode mode : matchingModes) {
try {
device.setDisplayMode(mode);
System.out.println(mode.getWidth() + "x" + mode.getHeight() + " " + mode.getBitDepth() + " @ " + mode.getRefreshRate());
break;
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
System.err.println("!! No matching modes available");
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.err.println("Change display mode not supported");
}
} else {
System.err.println("Full screen not supported");
}
}

public static class TestPane extends JPanel {

private boolean spaced = false;

public TestPane() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
requestFocusInWindow(true);
if (e.getClickCount() == 2) {
SwingUtilities.windowForComponent(TestPane.this).dispose();
}
}
});

InputMap im = getInputMap();
ActionMap am = getActionMap();

im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "spaced-pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true), "spaced-released");
am.put("spaced-pressed", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
spaced = true;
repaint();
}
});
am.put("spaced-released", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
spaced = false;
repaint();
}
});

requestFocusInWindow(true);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
String text = getWidth() + "x" + getHeight();
FontMetrics fm = g.getFontMetrics();
int x = (getWidth() - fm.stringWidth(text)) / 2;
int y = (getHeight() - fm.getHeight()) / 2;
g.drawString(text, x, y + fm.getAscent());

GraphicsDevice device = GraphicsEnvironment
.getLocalGraphicsEnvironment().getDefaultScreenDevice();

DisplayMode mode = device.getDisplayMode();
text = mode.getWidth() + "x" + mode.getHeight() + " " + mode.getBitDepth() + " @ " + mode.getRefreshRate();
x = (getWidth() - fm.stringWidth(text)) / 2;
y += fm.getHeight();
g.drawString(text, x, y + fm.getAscent());

text = "Spaced [" + spaced + "]";
x = (getWidth() - fm.stringWidth(text)) / 2;
y += fm.getHeight();
g.drawString(text, x, y + fm.getAscent());
}

}
}

Is it possible to Enable full screen exclusive mode if isDisplayChangeSupported() shows its not available

You are confusing two entirely different features:

  1. Full Screen Window

    Setting a full screen window always works. As the documentation says:

    The entered full-screen mode may be either exclusive or simulated. Exclusive mode is only available if isFullScreenSupported returns true.

    So when isFullScreenSupported returns false, it still works but is simulated.

  2. Display mode changes

    are about changing the resolution and/or color depth of the screen. They may require setting a full screen window first, as a prerequisite, but when display mode changes are not supported, full screen window still works:

    Sets the display mode of this graphics device. This is only allowed if isDisplayChangeSupported() returns true and may require first entering full-screen exclusive mode using setFullScreenWindow(java.awt.Window) providing that full-screen exclusive mode is supported (i.e., isFullScreenSupported() returns true).

Full screen Window won't get keyboard input using KeyListener or KeyBoardFocusManager

Why are you using AWT components in your Swing GUI? I fear (but don't know for sure) that by doing this, you may be losing some of the Swing functionality.

If you are only capturing select key select key strokes to control the game, consider using Key Bindings.

Edit:

No, the AWT components aren't at fault, but still probably should not be used.

Edit 2:

Your top level Window is not focused for some reason. Continuing to test code...

Edit 3:

Using a JFrame worked for me:

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

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

@Override
public void run() {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
if (gs.isFullScreenSupported()) {
SpaceInvaderUI spaceInvaderUI = new SpaceInvaderUI(gs.getDefaultConfiguration());
gs.setFullScreenWindow(spaceInvaderUI);
} else {
JOptionPane.showMessageDialog(null,
"Does not support full screen!", "Error 0x01",
JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
}
});
}
}

// class SpaceInvaderUI extends JWindow {
class SpaceInvaderUI extends JFrame {

private JPanel drawingPanel;
private Image background;
private JButton btnExit;

public SpaceInvaderUI(GraphicsConfiguration gc) {
super(gc);
createWindow();
addKeyBindings();
setUndecorated(true);
}

private void addKeyBindings() {
int condition = JPanel.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = drawingPanel.getInputMap(condition );
ActionMap actionMap = drawingPanel.getActionMap();

boolean released = false;
KeyStroke upArrowKeyStrokePressed = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, released );
String upArrowPressed = "up arrow pressed";
inputMap.put(upArrowKeyStrokePressed , upArrowPressed);
actionMap.put(upArrowPressed, new AbstractAction() {

@Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("up arrow pressed");
}
});

released = true;
String upArrowReleased = "up arrow released";
KeyStroke upArrowKeyStrokeReleased = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, released );
inputMap.put(upArrowKeyStrokeReleased , upArrowReleased);
actionMap.put(upArrowReleased , new AbstractAction() {

@Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("up arrow released");
}
});

}

private void createComponents() throws HeadlessException {
drawingPanel = new DrawingPanel(background, this);
btnExit = new JButton("Exit");
}

private void createWindow() {
createComponents();
addListeners();
addComponentsToWindow();
}

private void addComponentsToWindow() {
add(drawingPanel, BorderLayout.CENTER);
add(btnExit, BorderLayout.SOUTH);
}

private void addListeners() {
// KeyboardFocusManager manager = KeyboardFocusManager
// .getCurrentKeyboardFocusManager();
// manager.addKeyEventDispatcher(new MyDispatcher());
btnExit.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
});
}
//
// private class MyDispatcher implements KeyEventDispatcher {
//
// @Override
// public boolean dispatchKeyEvent(KeyEvent e) {
// System.out.println("in dispatch. KeyEvent := " + e);
// if (e.getID() == KeyEvent.KEY_PRESSED) {
// System.out.println("pressed");
// System.exit(0);
// } else if (e.getID() == KeyEvent.KEY_RELEASED) {
// System.out.println("released");
// System.exit(0);
// } else if (e.getID() == KeyEvent.KEY_TYPED) {
// System.out.println("Typed");
// System.exit(0);
// }
// return false;
// }
// }
}

class DrawingPanel extends JPanel {

private final Image background;
private final SpaceInvaderUI invaderUI;

DrawingPanel(Image background, SpaceInvaderUI invaderUI) {
this.background = background;
this.invaderUI = invaderUI;
setBackground(Color.pink);
}

@Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
}
}


Related Topics



Leave a reply



Submit