开发者

Java KeyListener in separate class

开发者 https://www.devze.com 2023-02-13 21:46 出处:网络
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...

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开发者_如何学C:

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?


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


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号