2

所以我在这里有我的主类,基本上创建一个新的 jframe 并向它添加一个世界对象。世界对象基本上是所有绘图和按键监听发生的地方......

public class Blobs extends JFrame{

    public Blobs() {
        super("Blobs :) - By Chris Tanaka");
        setVisible(true);
        setResizable(false);
        setSize(1000, 1000);
        setIgnoreRepaint(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        add(new World());
    }

    public static void main(String[] args) {
        new Blobs();
    }
}

您将如何从世界级获得关键输入?(到目前为止,我的世界级扩展了一个 jpanel 并实现了一个 keylistener。在构造函数中我 addKeyListener(this)。我也有这些方法,因为它们是自动实现的:

public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_W)
        System.out.println("Hi");
}

public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}

但是,这似乎不起作用?

4

3 回答 3

4

如果您想通知“观察班”您的世界级发生了 KeyPress 事件,那么这是使用观察员的好时机。该结构会是这样的:

public interface Observer
{ 
   public void update(KeyEvent keyEvent);
}

public interface Observable
{
   public void NotifyObservers(KeyEvent keyEvent);
}

public class World implements KeyListener, Observable
{
   private ArrayList<Observer> obsList;

   public World()
   {
      obsList = new ArrayList();
   }

   public void keyPressed(KeyEvent e) 
   {
      NotifyObservers(e);
   }

   public void keyReleased(KeyEvent e) {}
   public void keyTyped(KeyEvent e) {}

   public void NotifyObservers(KeyEvent keyEvent)
   {
       for(Observer obs : obsList)
       {
           obs.update(keyEvent);
       }
   }

   public void AddObserver(Observer obs)
   {
       if (obs != null)
          obsList.add(obs);
   }

   public void DelObserver(Observer obs)
   {
       if (obs != null)
          obsList.remove(obs);
   }
}

public class Blobs extends JFrame implements Observer
{

    public Blobs() 
    {
        super("Blobs :) - By Chris Tanaka");

        //Register this instance of Blobs as an observer that is stored in the World's
        //obsList ArrayList field
        World world = new World();
        world.addObserver(this);

        setResizable(false);
        setSize(1000, 1000);
        setIgnoreRepaint(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        getContentPane().add(world);
        this.addKeyListener(world);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Blobs();
    }

    public void update(KeyEvent keyEvent)
    {
       //do whatever here when key event occurs
    }
}

所以这里的最终结果是你可以让 Any 类实现我定义的 obsList 的 Observer 接口部分。然后,当一个 keyevent 发生时,它将调用 NotifyObservers() 方法,该方法遍历列表并调用 Observing 类中的 update() 方法。

编辑:

如果您愿意,您可以让 World 和 Battle 类以自己的方式处理关键事件。

public class Battle implements Observer
{

   public void update(KeyEvent e)
   {
      // do processing here
   }
}

public class Blobs implements Observer
{
   public void update(KeyEvent e)
   {
      // do processing here
   }
}

您只需要像我在 Blobs 中所做的那样,在某个时候将战斗作为观察者添加到您的 World 类中

worldInstance.addObserver(new Battle());

此外,如果您想使用标志只允许某些类处理键事件,那么您可以简单地更新接口以允许将标志传递给更新方法,如下所示:

public interface Observer
{
   public void update(object isFor, KeyEvent e);
}

那么你的观察者更新方法会有这样的流程:

public class Battle 
{
   public void update(object flag, KeyEvent e)
   {
        if (flag instanceof Battle)
        {
            //now do your work
        }
   }
}

这也意味着更新 Observable 接口和实现器中的 notify 方法

于 2011-02-27T05:23:07.260 回答
1

如果您的 Worls 类实现 KeyListener,那么执行您尝试做的事情的一种方法是像这样更改 Blobs 构造函数,

 public Blobs() {
        super("Blobs :) - By Chris Tanaka");
        setVisible(true);
        setResizable(false);
        setSize(1000, 1000);
        setIgnoreRepaint(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        World world = new World();
        getContentPane().add(world);
        this.addKeyListener(world);
        setVisible(true);
 }
于 2011-02-27T05:14:14.563 回答
1

IT 不起作用,因为默认情况下 JPanel 没有获得焦点。可以通过将其 focusable 属性设置为 true 并请求焦点来解决。

但是话虽如此,我认为您的 JPanel 类不实现侦听器接口很重要,因为您最好为侦听器使用匿名内部类。使用键绑定而不是键侦听器可能会更好,但根据目前提供的数据,我无法判断。

于 2011-02-27T05:19:48.323 回答