全屏独占模式键输入只需 Window
Full Screen Exclusive Mode Key Input with just a Window
我正在开发一个使用全屏独占的小游戏,我需要能够接收玩家的键盘输入。
在我的程序中,我有一个 Window 设置为全屏独占,还有一个渲染循环。
Window创作:
private void initialize() {
//This is used for my game loop...
running = true;
//Create the instance variable 'window' here.
window = new Window(null);
//Ignoring OS paint requests...
window.setIgnoreRepaint(true);
//Set the window to full screen exclusive.
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(window);
...
游戏循环:
private void loop() {
Graphics graphics = window.getGraphics();
graphics.setColor(Color.CYAN);
graphics.fillRect(0, 0, 1920, 1080);
graphics.dispose();
}
我的导入:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Window;
现在,这工作正常。就像它应该的那样。它在我的屏幕上呈现一个青色矩形,但是,我 需要能够检测用户何时按下按键,例如按 Escape
关闭程序,等等。 我不知道该怎么做。 :(
我已经尝试将 KeyListener
添加到我的 window
(没有用)。
我已经尝试将 JPanel
添加到我的 window
并向其添加一个监听器(也没有用)。
我已经尝试请求关注我的 JPanel
并在上面做同样的事情。
我尝试用 KeyListener 制作 JFrame
,然后将其传递到我的 window
的构造函数中。
我尝试将相同的 JFrame
与键绑定传递给我的 window
,而不是 KeyListener。
显然,上面的 none 有效。 (没有抛出错误,当我按下一个键或使用 System.exit(int);
退出程序时,我根本无法让程序在我的 sysout
中输出文本)我已经取出了所有没有的东西' 从上面的代码为我工作;我目前有一个 window 和一个游戏循环。 如果我还有其他方法可以实现全屏独占的Key Input,请告知(我感觉好像有专门针对全屏独占的常规方式,但是我没有还没有找到一个。)或者,如果您认为有一种方法可以获得我尝试过的方法之一(也许您认为我做错了什么),请告诉我。 (此时我有点绝望)。
我认为击键的默认事件处理是您只能从可聚焦的组件中获取它们,即 text-field。但是,引用此 post,您可以尝试使用将自定义 KeyEventDispatcher
(我认为这是 AWT 的基础 event-handling)添加到 KeyboardFocusManager
.
使用键绑定的示例。真的很简单,也演示了 DisplayMode
的用法,如果你愿意的话,但是一旦它是 运行,只需按住 space,它就会更新,松开它,它就会更新。双击关闭 ;)
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());
}
}
}
我正在开发一个使用全屏独占的小游戏,我需要能够接收玩家的键盘输入。
在我的程序中,我有一个 Window 设置为全屏独占,还有一个渲染循环。
Window创作:
private void initialize() {
//This is used for my game loop...
running = true;
//Create the instance variable 'window' here.
window = new Window(null);
//Ignoring OS paint requests...
window.setIgnoreRepaint(true);
//Set the window to full screen exclusive.
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(window);
...
游戏循环:
private void loop() {
Graphics graphics = window.getGraphics();
graphics.setColor(Color.CYAN);
graphics.fillRect(0, 0, 1920, 1080);
graphics.dispose();
}
我的导入:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Window;
现在,这工作正常。就像它应该的那样。它在我的屏幕上呈现一个青色矩形,但是,我 需要能够检测用户何时按下按键,例如按 Escape
关闭程序,等等。 我不知道该怎么做。 :(
我已经尝试将 KeyListener
添加到我的 window
(没有用)。
我已经尝试将 JPanel
添加到我的 window
并向其添加一个监听器(也没有用)。
我已经尝试请求关注我的 JPanel
并在上面做同样的事情。
我尝试用 KeyListener 制作 JFrame
,然后将其传递到我的 window
的构造函数中。
我尝试将相同的 JFrame
与键绑定传递给我的 window
,而不是 KeyListener。
显然,上面的 none 有效。 (没有抛出错误,当我按下一个键或使用 System.exit(int);
退出程序时,我根本无法让程序在我的 sysout
中输出文本)我已经取出了所有没有的东西' 从上面的代码为我工作;我目前有一个 window 和一个游戏循环。 如果我还有其他方法可以实现全屏独占的Key Input,请告知(我感觉好像有专门针对全屏独占的常规方式,但是我没有还没有找到一个。)或者,如果您认为有一种方法可以获得我尝试过的方法之一(也许您认为我做错了什么),请告诉我。 (此时我有点绝望)。
我认为击键的默认事件处理是您只能从可聚焦的组件中获取它们,即 text-field。但是,引用此 post,您可以尝试使用将自定义 KeyEventDispatcher
(我认为这是 AWT 的基础 event-handling)添加到 KeyboardFocusManager
.
使用键绑定的示例。真的很简单,也演示了 DisplayMode
的用法,如果你愿意的话,但是一旦它是 运行,只需按住 space,它就会更新,松开它,它就会更新。双击关闭 ;)
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());
}
}
}