我目前正在尝试将基于Java的平台程序作为一种自学成才的方式来自学Java Swing。我目前在JFrame中有一个JPanel,由w-a-s-d控制。我目前在记事本中编码,并使用命令行来运行并密切注意脚本。 (我知道,没有IDE是愚蠢的,只是现在无法打扰)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PanelExample {
private int dx;
private int dy;
private static javax.swing.Timer t;
boolean x1 = false;
boolean x2 = false;
boolean y1 = false;
boolean y2 = false;
PanelExample() {
JFrame f= new JFrame("Panel Example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p= new JPanel();
p.setBounds(50,50,20,20);;
p.setBackground(Color.red);
f.add(p);
f.setSize(700,400);
f.setLocationRelativeTo(null);
f.setLayout(null);
f.setVisible(true);
new Timer(20, new ActionListener(){
public void actionPerformed(ActionEvent arg0){
int bx = p.getLocation().x;
int by = p.getLocation().y;
if (x1 == true) {
p.setLocation(p.getLocation().x + 5, p.getLocation().y);
}
else {
p.setLocation(p.getLocation().x, p.getLocation().y);
}
if (x2 == true) {
p.setLocation(p.getLocation().x - 5, p.getLocation().y);
}
else {
p.setLocation(p.getLocation().x, p.getLocation().y);
}
if (y1 == true) {
p.setLocation(p.getLocation().x, p.getLocation().y + 5);
}
else {
p.setLocation(p.getLocation().x, p.getLocation().y);
}
if (y2 == true) {
p.setLocation(p.getLocation().x, p.getLocation().y - 5);
}
else {
p.setLocation(p.getLocation().x, p.getLocation().y);
}
if (bx < 0) {
p.setLocation(p.getLocation().x = 0, p.getLocation().y);
}
if (bx > 665) {
p.setLocation(p.getLocation().x = 665, p.getLocation().y);
}
if (by < 0) {
p.setLocation(p.getLocation().x, p.getLocation().y = 0);
}
if (by > 340) {
p.setLocation(p.getLocation().x, p.getLocation().y = 340);
}
System.out.println("X value: " + bx + " | Y value: " + by);
}
}).start();
f.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int ax = e.getKeyCode();
int bx = p.getLocation().x;
int by = p.getLocation().y;
switch(ax)
{
//the numbers on the cases corresond with w-a-s-d
//this is for the key s to go down
case 83:
if (by < 340){
y1 = true;
break;
}
//this is for the key d or right
case 68:
if (bx < 665){
x1 = true;
break;
//this is for the key w or up
}
case 87:
if (by > 0){
y2 = true;
break;
}
//this is for the key a or left
case 65:
if (bx > 0){
x2 = true;
break;
}
}
}
@Override
public void keyReleased(KeyEvent e) {
System.out.println("Key released code=" + e.getKeyCode());
int ax = e.getKeyCode();
switch(ax)
{
case 83:
y1 = false;
break;
case 68:
x1 = false;
break;
case 87:
y2 = false;
break;
case 65:
x2 = false;
break;
}
}
});
}
public static void main(String args[]) {
new PanelExample();
}
}
我的问题是,当我的物体接触到顶部或右侧的墙壁时,一半时间分别进入左上角或右上角。当发生这种情况时,对于顶壁,键d停止工作,而对于右壁,键s停止工作。我试图设置if语句,如果它越过边界,则停止所有移动,但这无济于事。我究竟做错了什么?
最佳答案
首先,您不应该使用“幻数”。例如:
case 83:
API提供的变量使您的代码更易于阅读:
case KeyEvent.VK_S:
我的问题是,当我的物体碰到顶部或右侧的墙壁时
不知道发生了什么,但我怀疑您有几个问题:
您将KeyListener添加到错误的组件。当您将其添加到框架的内容窗格中时,您将其添加到框架中,因为您将红色面板添加到了内容窗格中。那就是您的红色面板永远不会到达框架的顶部,因为标题栏是框架的一部分。因此,当您进行0测试时,它必须与框架的内容窗格相关。
我看到硬编码的值对我没有任何意义。 665是什么?那是宽度吗?不要硬编码值。如果用户调整框架大小怎么办?
您可以在KeyListener中使用以下代码动态获取大小:
Component c = (Component)e.getSource();
int width = c.getWidth();
但是,如果进行了上述更改,则代码将停止工作,因为KeyEvent仅针对具有焦点的组件生成,并且面板将不具有焦点,因为默认情况下该面板不可聚焦。论坛中的一般建议是使用键绑定,而不是KeyListener。
查看Motion Using the Keyboard的工作示例,其中包含以上所有建议。