Java KeyListener 在单独的类中

发布于 2024-10-19 13:14:29 字数 824 浏览 8 评论 0原文

所以我在这里有我的主类,基本上创建一个新的 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) {}

但这似乎不起作用?

So I have my main class here, where basically creates a new jframe and adds a world object to it. The world object is basically where all drawing and keylistening would take place...

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();
    }
}

How exactly would you get key input from the world class?
(So far I have my world class extending a jpanel and implementing a keylistener. In the constructor i addKeyListener(this). I also have these methods since they are auto implemented:

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) {}

However this does not seem to work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吃颗糖壮壮胆 2024-10-26 13:14:29

如果您想通知“观察类”在您的世界类中发生了 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
    }
}

所以这里的最终结果是你可以使任何实现 Observer 接口的类成为我定义的 obsList 的一部分。然后,当发生键事件时,它将调用 NotifyObservers() 方法,该方法循环访问列表并调用 Observing 类中的 update() 方法。

编辑:

如果您愿意,您可以让世界和战斗类以自己的方式处理关键事件。

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
   }
}

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

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 接口和实现者中的通知方法

This is a great time to utilize an Observer if you wanted to inform "observing classes" that a KeyPress event occurred in your world class. The structure would like something like this:

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
    }
}

SO the end result here is that you can make Any class that implements the Observer interface part of the obsList I defined. Then when a keyevent occurs it will invoke the NotifyObservers() method which iterates through the list and invokes the update() method in the Observing class.

EDIT:

You can have both the World and Battle classes handling key events in their own ways if you so desired.

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
   }
}

You would just need to at some point add battle as an observer to your World class like I did in Blobs

worldInstance.addObserver(new Battle());

In addition, if you wanted to use flags to only allow certain classes to process keyevents then you could simply update the interface to allow passing the flag to the update method as so:

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

then you Observer update methods would have this kind of flow:

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

This also means updating the notify method in the Observable interface and implementor

星軌x 2024-10-26 13:14:29

如果您的 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);
 }

If your Worls class implements KeyListener, then one way to do what you are trying to do is to change Blobs constructor like this,

 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);
 }
放肆 2024-10-26 13:14:29

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

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

IT doesn't work because by default JPanels don't get the focus. It could be solved by setting its focusable property to true and requesting the focus.

But having said that, I think that it's important that your JPanel class not implement a listener interface as you're much better off using an anonymous inner class for your listener. You may even be better off using key bindings and not a key listener, but I can't tell based on the data that has been so far presented.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文