- = UPDATE = -
事实证明问题不在于Java,而在于我的Apple键盘。按住一个字母键会打开一个菜单,打破我的Java程序。通过禁用该菜单弹出窗口,我的KeyListener和我的Key Bindings都可以正常工作。谢谢大家的答案。
问题
我在谷歌和StackOverflow上搜索了我的问题的答案,但无济于事。我发现的所有问题都有主类扩展JComponent,JFrame,JPanel等,而不是Canvas。
现在我的问题:
在程序运行时,我无法让Java KeyListener合作。当我开始我的程序时,一切都像往常一样。然而,当我开始按键并移动物品(使用所述键)时,程序开始延迟并花费更多时间进行按键注册。突然间,他们KeyListener完全中断,我没有输入(即使keyPressed方法中的System.out.println语句显示没有活动)。我有三个与我的KeyListener有关的类。
如果有帮助,该程序的目标是使用BufferedImage类绘制来自不同数学函数的点,如正弦波。我已经评论了我能做到的最好,而不是超级评论者,但我可以尽我所能澄清任何代码的目的。
首先,我的Screen类(使用BufferStrategy在JFrame上绘制内容):
SHEETS.spreadsheets().values().update(spreadsheetId=SHEET_ID, range='A1',
body={'values': rows}, valueInputOption='RAW').execute()
其次,我的Keyboard类(中断的KeyListener):
package com.elek.waves.graphics;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import com.elek.waves.graphics.math.Controller;
import com.elek.waves.graphics.math.Graph;
import com.elek.waves.input.Keyboard;
/**
* The engine of the entire Waves project. Processes the BufferedImage and puts the JFrame
* on the screen. Uses other classes to calculate where to put pixels (what color each pixel
* in the array should be) and get keyboard input.
*
* @author my name
* @version 1.0
*/
public class Screen extends Canvas {
/**
* Holds some *important* number that makes Java happy.
*/
private static final long serialVersionUID = 1L;
/**
* Constant (and static) dimensions of the window.
*/
public static final int WIDTH = 800, HEIGHT = 800;
/**
* Frame that will contain the BufferedImage and all its glory.
*/
private JFrame frame;
/**
* BufferedImage processes the pixel array and translates it into fancy screen magic.
*/
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
/**
* Holds color data for each pixel on the screen. Each pixel has an integer value equivalent
* to the hexadecimal RGB value for whatever color this pixel is supposed to be.
*/
private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
/**
* Graph object to draw the lines on.
*/
private Graph graph;
/**
* Controller object to control the graph.
*/
private Controller controller;
/**
* Keybaord object to use as a key-listener.
*/
private Keyboard key;
/* -- Constructor -- */
/**
* Creates a new Screen object. Initializes the JFrame object.
*/
public Screen() {
frame = new JFrame("Magic!");
graph = new Graph(pixels);
key = new Keyboard();
controller = new Controller(key, graph);
addKeyListener(key);
}
/* -- Methods -- */
/**
* Called once and only once by the main method. Repeatedly calls the update and render methods
* until the program stops running.
*/
private void start() {
this.requestFocus();
this.requestFocusInWindow();
while (true) {
update();
render();
}
}
/**
* Called by the start method repeatedly. First, clears the screen of the previous image in
* order to prevent ghost-imaging or blurring. Then, updates the pixel array to whatever it
* needs to be for the next iteration of the render method.
*/
private void update() {
// Update the keyboard input
key.update();
// Update the controller
controller.update();
// Clean up the screen and then graph the line
clearScreen();
graph.drawWave();
}
/**
* Called by the start method repeatedly. Draws the pixel array onto the JFrame using the
* BufferedImage magic.
*/
private void render() {
// Initialize buffer strategies
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(2);
return;
}
// Physically update the actual pixels on the image
Graphics g = (Graphics2D) bs.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
/**
* Clears the screen by setting every pixel in the pixel array to black. Used to prevent
* ghost-images or blurring.
*/
public void clearScreen() {
for (int i = 0; i < pixels.length; i++)
pixels[i] = 0;
}
/**
* Main method to run the program. Creates a Screen object with a BufferedImage to display
* pixels however the other classes decide to. All this does is set up the JFrame with the
* proper parameters and properties to get it up and running.
*
* @param args A String array of random arguments that Java requires or it gets fussy
*/
public static void main(String[] args) {
// Create Screen object
Screen screen = new Screen();
screen.frame.add(screen);
screen.frame.pack();
screen.frame.setSize(WIDTH, HEIGHT);
screen.frame.setLocationRelativeTo(null);
screen.frame.setResizable(false);
screen.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
screen.frame.setVisible(true);
screen.start();
}
}
第三,我的Controller类(使用KeyListener来控制程序):
package com.elek.waves.input;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
* Gets the user's key strokes and determines which keys are down at a given time.
*
* @author my name
* @version 1.0
*/
public class Keyboard implements KeyListener {
/**
* Holds the state of 120 keys (true if they're down, false if they're not).
*/
private boolean[] keys = new boolean[120];
/**
* Holds the state of the "useful" keys (true if down, false if not).
*/
public boolean w, a, s, d, up, down, left, right;
/**
* Determines if the "useful" keys are down or not. Sets the variables to true if they're down and
* false if they're up.
*/
public void update() {
w = keys[KeyEvent.VK_W];
a = keys[KeyEvent.VK_A];
s = keys[KeyEvent.VK_S];
d = keys[KeyEvent.VK_D];
up = keys[KeyEvent.VK_UP];
down = keys[KeyEvent.VK_DOWN];
left = keys[KeyEvent.VK_LEFT];
right = keys[KeyEvent.VK_RIGHT];
}
/**
* Changes the state of the pressed key's corresponding boolean in the array to true.
*/
public void keyPressed(KeyEvent e) {
keys[e.getKeyCode()] = true;
}
/**
* Changes the state of the pressed key's corresponding boolean in the array to false.
*/
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
public void keyTyped(KeyEvent e) {
}
}
我找到了几个有用的人说使用KeyBindings而不是KeyListener。但是,我过去成功使用过KeyListener,如果可能的话,我想让它再次运行。如果KeyBindings是绝对必要的,我想我可以进行切换,但我更愿意,如果不是这样的话。
提前谢谢大家!
答案 0 :(得分:1)
Canvas
会遇到与所有其他组件相同的问题,键盘焦点丢失,这就是我们通常不建议使用KeyListener
的原因。
首先,您需要使Canvas
具有焦点,请参阅Canvas#setFocusable
下一个更困难的问题是请求键盘焦点,您可以使用Canvas#requestFocusInWindow
,但任何需要键盘焦点的组件都会窃取它。
根据您的操作,您可以简单地将调用置于更新循环中,但您需要注意,如果您想在同一窗口中询问用户的输入,则会出现问题(画布偷走焦点)
由于在键盘控制器中使用了一个数组,我遇到了一些边界索引的问题,我将其转换为Set
而不是......
public class Keyboard implements KeyListener {
/**
* Holds the state of 120 keys (true if they're down, false if they're
* not).
*/
// private boolean [] keys = new boolean [120];
/**
* Holds the state of the "useful" keys (true if down, false if not).
*/
private Set<Integer> keys;
/**
* Determines if the "useful" keys are down or not. Sets the variables
* to true if they're down and false if they're up.
*/
public void update() {
keys = new HashSet<>(8);
}
public boolean isKeyPressed(int key) {
return keys.contains(key);
}
public boolean isWPressed() {
return isKeyPressed(KeyEvent.VK_W);
}
public boolean isAPressed() {
return isKeyPressed(KeyEvent.VK_A);
}
public boolean isSPressed() {
return isKeyPressed(KeyEvent.VK_S);
}
public boolean isDPressed() {
return isKeyPressed(KeyEvent.VK_D);
}
public boolean isUpPressed() {
return isKeyPressed(KeyEvent.VK_UP);
}
public boolean isDownPressed() {
return isKeyPressed(KeyEvent.VK_DOWN);
}
public boolean isLeftPressed() {
return isKeyPressed(KeyEvent.VK_LEFT);
}
public boolean isRightPressed() {
return isKeyPressed(KeyEvent.VK_RIGHT);
}
/**
* Changes the state of the pressed key's corresponding boolean in the
* array to true.
*/
public void keyPressed(KeyEvent e) {
System.out.println("Pressed = " + e.getKeyCode());
keys.add(e.getKeyCode());
}
/**
* Changes the state of the pressed key's corresponding boolean in the
* array to false.
*/
public void keyReleased(KeyEvent e) {
System.out.println("Released = " + e.getKeyCode());
keys.remove(e.getKeyCode());
}
public void keyTyped(KeyEvent e) {
}
}
我还在渲染循环中添加了一个小延迟,因此您不会阻塞系统
private void start() {
setFocusable(true);
while (true) {
this.requestFocusInWindow();
update();
render();
try {
Thread.sleep(16);
} catch (InterruptedException ex) {
}
}
}
答案 1 :(得分:0)
尝试
f = open('input1.csv') # create file object
userInput = f.read()
seperated = userInput.split(',')
wordsDict = {}
for word in seperated:
if word not in wordsDict:
wordsDict[word] = 1
else:
wordsDict[word] = int(wordsDict.get(word)) + 1
for i in wordsDict:
print i, wordsDict[i]
尽管这是在import javax.swing.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Main {
public static void main(String[] argv) throws Exception {
JTextField textField = new JTextField();
textField.addKeyListener(new MKeyListener());
JFrame jframe = new JFrame();
jframe.add(textField);
jframe.setSize(700, 700);
jframe.setVisible(true);
}
}
class MKeyListener extends KeyAdapter {
@Override
public void keyPressed(KeyEvent event) {
System.out.println(event.getKeyCode)
if(event.getKeyCode() = \\key code here\\){
System.out.println("True")
}else{System.out.println("False")
中运行的,但不应有任何问题