Java 如何在 JFrame 中使用 KeyListener?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21997130/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use KeyListener with JFrame?
提问by user3183679
So, I was trying to make a rectangle move with a KeyEvent
(KeyListener
) and whenever I try to hit the key, the rectangle doesn't move.
所以,我试图用KeyEvent
( KeyListener
)移动矩形,每当我尝试按下键时,矩形都不会移动。
The rectangle is drawn, but whenever I hit the left
and right
keys, nothing happens.
I have two classes, one is my main class with the keyEvents and the frame and the other, draws the rectangle and holds the function to move the rectangle.
矩形已绘制,但每当我按下left
和right
键时,什么也没有发生。我有两个类,一个是带有 keyEvents 和框架的主类,另一个是绘制矩形并保存移动矩形的函数。
Here is my code:
这是我的代码:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class mainFrame extends JFrame implements KeyListener{
mainDraw Draw = new mainDraw();
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_D){
Draw.moveRight();
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {}
public mainFrame()
{
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public static void main(String[] args) {
mainFrame M1 = new mainFrame();
mainDraw Draw = new mainDraw();
JFrame frame = new JFrame("Square Move Practice");
//frame
frame.setVisible(true);
frame.setResizable(false);
frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(Draw);
}
}
And now the second class:
现在是第二堂课:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
public class mainDraw extends JComponent{
public int x = 50;
public int y = 50;
public void paint(Graphics g){
g.drawRect(x, y, 50, 50);
g.fillRect(x, y, 50, 50);
g.setColor(Color.BLACK);
}
public void moveRight()
{
x = x + 5;
y = y + 0;
repaint();
}
}
Please tell me how I can move the rectangle. Thanks in advance!
请告诉我如何移动矩形。提前致谢!
采纳答案by Jhonatan
The rectangle is not moving because you are not using JFrame
correctly. You have to assign frame
to new mainFrame()
instead of ignoring the instantiated mainFrame
object.
矩形没有移动,因为您没有JFrame
正确使用。您必须分配frame
给new mainFrame()
而不是忽略实例化的mainFrame
对象。
There are several other issues as @MadProgrammer points out.
正如@MadProgrammer 指出的那样,还有其他几个问题。
Here is the code that fixes some of the issues:
以下是修复部分问题的代码:
mainFrame.java
主框架.java
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class mainFrame extends JFrame implements KeyListener{
private mainDraw draw;
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed");
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode()== KeyEvent.VK_RIGHT)
draw.moveRight();
else if(e.getKeyCode()== KeyEvent.VK_LEFT)
draw.moveLeft();
else if(e.getKeyCode()== KeyEvent.VK_DOWN)
draw.moveDown();
else if(e.getKeyCode()== KeyEvent.VK_UP)
draw.moveUp();
}
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped");
}
public mainFrame(){
this.draw=new mainDraw();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
mainFrame frame = new mainFrame();
frame.setTitle("Square Move Practice");
frame.setResizable(false);
frame.setSize(600, 600);
frame.setMinimumSize(new Dimension(600, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(frame.draw);
frame.pack();
frame.setVisible(true);
}
});
}
}
mainDraw.java
主绘图程序
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
public class mainDraw extends JComponent {
public int x = 50;
public int y = 50;
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(x, y, 50, 50);
g.fillRect(x, y, 50, 50);
g.setColor(Color.BLACK);
}
public void moveRight() {
x = x + 5;
repaint();
}
public void moveLeft() {
x = x - 5;
repaint();
}
public void moveDown() {
y = y + 5;
repaint();
}
public void moveUp() {
y = y - 5;
repaint();
}
}
BTW, use SwingUtilities
to put the gui update code because swing objects are not thread-safe.
顺便说一句,用于SwingUtilities
放置 gui 更新代码,因为 Swing 对象不是线程安全的。
回答by Jhonatan
You should add your listener in the mainDraw class, not your mainFrame.
你应该在 mainDraw 类中添加你的监听器,而不是你的 mainFrame。
It's a good practice not to handle key and mouse events in Frames and Windows.
在 Frames 和 Windows 中不处理键和鼠标事件是一个很好的做法。
o/
o/
回答by MadProgrammer
There are at least three issues...
至少有三个问题...
Firstly...
首先...
Your mainFrame
class extends
from JFrame
, but in your main
method, you create an instance of it and ignore it, by creating your own JFrame
.
您的mainFrame
类extends
来自JFrame
,但在您的main
方法中,您通过创建自己的JFrame
.
The KeyListener
is registered to the instance of mainFrame
, meaning, it's been ignored.
该KeyListener
注册到的情况下mainFrame
,这意味着,它被忽略。
You should get rid of extends JFrame
as it's just confusing the issue
你应该摆脱,extends JFrame
因为它只是混淆了问题
Secondly...
其次...
KeyListener
will only respond to key events when the component it is registered to is focusable AND has direct focus, this makes it unreliable.
KeyListener
只有当它注册到的组件是可聚焦的并且具有直接焦点时,才会响应关键事件,这使得它不可靠。
Instead, you should use the key bindings APIwith the Draw
panel, this will allow you to over come the focus issues.
相反,您应该将按键绑定 API与Draw
面板一起使用,这将允许您克服焦点问题。
Thirdly...
第三...
You've broken the paint chain, this means that when the rectangle moves, what was painted previously will still remain.
您已经破坏了绘制链,这意味着当矩形移动时,之前绘制的内容仍将保留。
You should refrain from overriding paint
and instead use paintComponent
. There are lots of reasons for this, but generally, it paints in the background, is called as updates to child components.
您应该避免覆盖paint
并使用paintComponent
. 这有很多原因,但一般来说,它在后台绘制,被称为对子组件的更新。
Finally, make sure you are calling super.paintComponent
before you do anything else, to ensure the Graphics
context is prepared for painting
最后,确保super.paintComponent
在执行任何其他操作之前调用,以确保Graphics
上下文已准备好进行绘制
Take a look at Performing Custom Paintingfor more details
查看执行自定义绘画以了解更多详细信息
回答by Sahan
I was trying to implement shortcut listeners to whole frame and not succeeded, Finally found a way. If you want to set listener even when focus to another component, You must add listeners to all components.
我试图为整个框架实现快捷方式侦听器但没有成功,终于找到了方法。如果您想设置监听器,即使焦点在另一个组件上,您必须为所有组件添加监听器。
Here is my code,
这是我的代码,
Call this in your constructor :
在您的构造函数中调用它:
setShortcutListener(this); // this = JFrame when you call in in constructor
Method setShortcutListener(JFrame frame) :
方法 setShortcutListener(JFrame frame) :
private void setShortcutListener(JFrame frame) {
List<Component> comp_list = Common.getAllComponents(frame);
for (Component component : comp_list) {
component.addKeyListener(getShortcutKeyListener());
}
}
Method getAllComponents(frame); Class Common is just a class,
方法 getAllComponents(frame); 类 Common 只是一个类,
public static List<Component> getAllComponents(final Container c) {
Component[] comps = c.getComponents();
List<Component> compList = new ArrayList<Component>();
for (Component comp : comps) {
compList.add(comp);
if (comp instanceof Container) {
compList.addAll(getAllComponents((Container) comp));
}
}
return compList;
}
Method getShortcutKeyListener() :
方法 getShortcutKeyListener() :
public static KeyListener getShortcutKeyListener() {
KeyListener listener = new KeyListener() {
@Override
public void keyReleased(KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_F3) {
// What you do when F3 key pressed
} else if (evt.getKeyCode() == KeyEvent.VK_F2) {
// What you do when F2 key pressed
}
}
@Override
public void keyTyped(KeyEvent e) {
// Do nothing
}
@Override
public void keyPressed(KeyEvent e) {
// Do nothing
}
};
return listener;
}
I think we have easy ways than this, But this code works exactly as expected. Key listeners works anywhere in form.
我认为我们有比这更简单的方法,但是这段代码完全按预期工作。关键侦听器以形式在任何地方工作。
Hope this answer will help someone. Thanks.
希望这个答案会对某人有所帮助。谢谢。