Java KeyListener в отдельном классе - PullRequest
2 голосов
/ 27 февраля 2011

Итак, у меня есть мой основной класс, где я в основном создаю новый 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 и реализующий список ключей. В конструкторе я добавляю 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) {}

Однако это не кажетсяработать?

Ответы [ 3 ]

3 голосов
/ 27 февраля 2011

Это прекрасное время для использования Обозревателя, если вы хотите сообщить «наблюдающим классам», что событие 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.Затем, когда происходит событие keyevent, он вызывает метод NotifyObservers (), который выполняет итерацию по списку и вызывает метод update () в классе Observing.

РЕДАКТИРОВАТЬ:

Вы можете иметь оба мираи боевые классы обрабатывают ключевые события по-своему, если хотите.

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, как я это сделал в Blobs

worldInstance.addObserver(new Battle());

Кроме того, если вы хотите использовать флаги, чтобы позволить только определенным классам обрабатывать ключевые события, вы можете просто обновить интерфейс, чтобы разрешить передачу флага методу обновления, следующим образом:

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

тогда у ваших методов обновления Observer будет такой поток:

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

Это также означает обновление метода notify в интерфейсе Observable и реализации

1 голос
/ 27 февраля 2011

Это не работает, потому что по умолчанию JPanels не получают фокус.Эту проблему можно решить, установив для ее свойства focusable значение true и запросив фокус.

Но, сказав это, я думаю, что важно, чтобы ваш класс JPanel не реализовывал интерфейс слушателя, поскольку вам гораздо лучше использоватьанонимный внутренний класс для вашего слушателя.Возможно, вам даже лучше использовать привязки клавиш, а не прослушиватель клавиш, но я не могу сказать, основываясь на данных, которые уже были представлены.

1 голос
/ 27 февраля 2011

Если ваш класс 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);
 }
...