gpt4 book ai didi

Java最后添加的按钮允许agent.move,其余则不允许

转载 作者:太空宇宙 更新时间:2023-11-04 07:23:15 25 4
gpt4 key购买 nike

我是java新手,一直致力于创建一个代码来获取汽车的小图片以使用按键移动。我的问题是当我向面板添加超过 1 个按钮时。我发布的代码中按钮的功能没什么,只是打印“button [i] clicked”消息。目的是让他们读取文件并根据文件中的数据更新汽车的位置。这应该是我的强化学习项目的一部分。我认为这将是学习java的好机会,因为这个“图形包”对于该项目来说不是必需的,只是一个“不错的”补充。代码在这里:

package graphics;

public class Board extends JPanel implements ActionListener {

private Timer timer;
private Agent agent;

private String button = "button.png";
private Image image;


protected JButton b1;
protected JButton b2;
protected JButton b3;

public Board() {

//Keylistener added for the agent to respond to arrow keys

addKeyListener(new TAdapter());
agent = new Agent();
timer = new Timer(10, this); //10ms timer calls action performed
timer.start();

//This part for the button.
ImageIcon i = new ImageIcon(this.getClass().getResource(button));
image = i.getImage();

b1 = new JButton("1", i);
b1.setVerticalTextPosition(AbstractButton.CENTER);
b1.setHorizontalTextPosition(AbstractButton.LEADING);
b1.setActionCommand("Active1");



b2 = new JButton("2", i);
b2.setVerticalTextPosition(AbstractButton.CENTER);
b2.setHorizontalTextPosition(AbstractButton.LEADING);
b2.setActionCommand("Active2");



b3 = new JButton("3", i);
b3.setVerticalTextPosition(AbstractButton.CENTER);
b3.setHorizontalTextPosition(AbstractButton.LEADING);
b3.setActionCommand("Active3");



b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);

add(b1); add(b2); add(b3);

setFocusable(true);
setBackground(Color.BLACK);
setDoubleBuffered(true);


}


public void paint(Graphics g) {
super.paint(g);

Graphics2D g2d = (Graphics2D)g;

//Transformations for the agent to be painted based upon its position and orientation

AffineTransform trans = new AffineTransform();

trans.rotate(Math.toRadians(agent.getTh()), agent.getX()+64, agent.getY()+64);
trans.translate(agent.getX(), agent.getY());

g2d.drawImage(agent.getImage(), trans, this); // Draws agent with said transformations

Toolkit.getDefaultToolkit().sync();
g.dispose();
}


public void actionPerformed(ActionEvent ae) {

b1.setEnabled(true);
b2.setEnabled(true);
b3.setEnabled(true);

if (ae.getActionCommand()=="Active1") {
b1.setEnabled(false);
b2.setEnabled(true);
b3.setEnabled(true);
System.out.println("Clicked 1");
agent.reset();
}



if(ae.getActionCommand()=="Active2") {
b1.setEnabled(true);
b2.setEnabled(false);
b3.setEnabled(true);
System.out.println("Clicked 2");
agent.reset();
}

if (ae.getActionCommand()=="Active3") {
b1.setEnabled(true);
b2.setEnabled(true);
b3.setEnabled(false);
System.out.println("Clicked 3");
agent.reset();


}

agent.move();
repaint();

}

private class TAdapter extends KeyAdapter {

public void keyReleased(KeyEvent e) {
agent.keyReleased(e);
}

public void keyPressed(KeyEvent e) {
agent.keyPressed(e);
}
}

}

现在,问题是这样的。如果我单击按钮 1 或按钮 2,其他按钮将被禁用,并且显示“单击 1(或 2)”,这很好。但不会调用 agent.move() 和 repaint() 。当我按下按键时汽车不动。如果我单击按钮 3,其他两个按钮将被禁用,汽车将随着按键移动。

如果我以不同的顺序添加按钮 add(b3);添加(b2);添加(b1);然后同样的情况发生,但这次按钮 1 工作正常。

最佳答案

问题:

  • 您的主要问题是焦点之一 - 当 JButton 获得焦点而 JPanel 失去焦点时,JPanel 的 KeyListener 将不起作用,因为 KeyListener 要求所监听的组件具有焦点,也不异常(exception)。
  • 一个糟糕的解决方案是强制 JPanel 始终保持焦点。如果您的窗口有 JButton,这将很糟糕;如果您需要显示 JTextField、JTextAreas 或其他文本组件,这将是灾难。
  • 更好的解决方案是不使用 KeyListener,因为它在 Swing 应用程序中存在很多问题,特别是它具有如上所述的焦点问题。请改用按键绑定(bind)。谷歌一下教程,了解有关此内容的详细信息。
  • 不要使用 == 来比较字符串,而是使用 equals(...)equalsIgnoreCase(...) 。问题是 == 检查对象相等性,字符串 A 是否与字符串 B 是同一个对象,而您不关心这一点。您想知道两个字符串是否以相同的顺序保存相同的字符,这就是这两个方法的用武之地。
  • 不要对 JVM 提供的 Graphics 对象进行 dispose(),因为这可能会扰乱组件边框、子组件的绘制,甚至产生其他副作用。
  • 不要在 JPanel 的 paint(...) 方法中绘制,而应在其 paintComponent(...) 方法中绘制,就像教程告诉您的那样。如果您不小心,在 paint(...) 中绘图可能会对组件的边框和子组件产生副作用,并且也没有默认双缓冲的好处,而默认双缓冲对于平滑动画很重要。 paintComponent(...) 解决了所有这些问题。
  • 说到这里,您应该 Google 并阅读 Swing 图形教程。您无法编造一些东西并希望它能起作用,图形编程将需要一种与您习惯的完全不同的方法。
  • 忽略 Andromeda 的线程建议。虽然他的本意是好的,但我建议你不要在后台线程中进行绘画。只需像您正在做的那样用 Swing Timer 移动汽车即可。后台线程有其用途,但不是在这里,因为计时器可以正常工作。当您有一个长时间运行的进程阻塞调用线程时,您将需要使用后台线程(当前代码中没有这种功能),因此不需要线程“修复”,事实上,如果您不非常小心地在 Swing 事件线程上进行 Swing 调用,则实际上是潜在的问题根源。但我们不知道你的“代理人”正在做什么。如果它正在调用长时间运行的代码或其中包含 Thread.sleep(...)wait()/notify() 的代码,那么是的,您将需要使用后台线程。
  • 但是,我们知道这不是您的主要问题,因为您的问题仅在添加焦点捕获器(JButton)后才开始。这再次强烈表明您的主要问题不是线程,而是 KeyListener 的使用及其焦点要求。

例如:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.*;
import java.util.EnumMap;
import javax.swing.*;

@SuppressWarnings("serial")
public class KeyBindingPanel extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = PREF_W;
private static final Stroke THICK_STROKE = new BasicStroke(5f,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
private static final int OVAL_WIDTH = 30;
private static final int OVAL_HEIGHT = 30;
private static final Color OVAL_COLOR = Color.red;
private static final Color BKGRD_COLOR = Color.black;
private static final int TIMER_DELAY = 20;
public static final int STEP = 2;
private int myX = 0;
private int myY = 0;
private JButton[] buttons = new JButton[3];
private int condition = WHEN_IN_FOCUSED_WINDOW;
private InputMap inputMap = getInputMap(condition);
private ActionMap actionMap = getActionMap();
private EnumMap<Direction, Boolean> directionMap = new EnumMap<Direction, Boolean>(
Direction.class);

public KeyBindingPanel() {
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton(new ButtonAction());
add(buttons[i]);
}
setBackground(BKGRD_COLOR);

for (final Direction direction : Direction.values()) {
directionMap.put(direction, Boolean.FALSE);

Boolean[] onKeyReleases = { Boolean.TRUE, Boolean.FALSE };
for (Boolean onKeyRelease : onKeyReleases) {
KeyStroke keyStroke = KeyStroke.getKeyStroke(
direction.getKeyCode(), 0, onKeyRelease);
inputMap.put(keyStroke, keyStroke.toString());
actionMap.put(keyStroke.toString(), new DirAction(direction,
onKeyRelease));
}
}

new Timer(TIMER_DELAY, new GameTimerListener()).start();
}

@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}

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

Graphics2D g2b = (Graphics2D) g.create();
g2b.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2b.setStroke(THICK_STROKE);
g2b.setColor(OVAL_COLOR);
g2b.drawOval(myX, myY, OVAL_WIDTH, OVAL_HEIGHT);

g2b.dispose(); // since I created this guy
}

private class GameTimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
for (Direction direction : Direction.values()) {
if (directionMap.get(direction)) {
myX += STEP * direction.getRight();
myY += STEP * direction.getDown();
}
}
repaint();
}
}

private class DirAction extends AbstractAction {
private Direction direction;
private boolean onRelease;

public DirAction(Direction direction, boolean onRelease) {
this.direction = direction;
this.onRelease = onRelease;
}

@Override
public void actionPerformed(ActionEvent evt) {
directionMap.put(direction, !onRelease); // it's the opposite!
}
}

private class ButtonAction extends AbstractAction {
public ButtonAction() {
super("Press Me!");
}

@Override
public void actionPerformed(ActionEvent e) {
JButton thisBtn = (JButton) e.getSource();
for (JButton btn : buttons) {
if (btn == thisBtn) {
btn.setEnabled(false);
} else {
btn.setEnabled(true);
}
}
}
}

private static void createAndShowGui() {
JFrame frame = new JFrame("KeyBindingPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new KeyBindingPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

enum Direction {
UP(KeyEvent.VK_UP, -1, 0), DOWN(KeyEvent.VK_DOWN, 1, 0), LEFT(
KeyEvent.VK_LEFT, 0, -1), RIGHT(KeyEvent.VK_RIGHT, 0, 1);

private int keyCode;
private int down;
private int right;

private Direction(int keyCode, int down, int right) {
this.keyCode = keyCode;
this.down = down;
this.right = right;
}

public int getKeyCode() {
return keyCode;
}

public int getDown() {
return down;
}

public int getRight() {
return right;
}

}

关于Java最后添加的按钮允许agent.move,其余则不允许,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18969592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com