2015-01-08 4 views
0

Надеюсь, этот вопрос не является повторением существующего! Я искал и не нашел хорошего ответа на мой вопрос. Вот он:Метод вызова класса объекта

У меня есть класс MyGame, который содержит объект-член Button. Всякий раз, когда нажимается эта кнопка, MyGame должен что-то делать.

class MyGame extends Application { 
    MyBoard board = new MyBoard(); 
    MyButton btn = new MyButton(); 

    public MyGame() { 
     board.add(btn); 
    } 

    // this method should be called whenever the button is clicked! 
    public void doSomething() { 
     doingSomething(); 
    } 
} 

class MyButton extends Button { 
    int someData; 

    // some code here 

    public MyButton() { 
     this.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent arg0) { 
       MyGame.doSomething(); // ==> NOT POSSIBLE!!! 
      } 
     }); 
    } 
} 

ли интерфейс быть лучшим способом, чтобы сделать связь между MyButton и MyGame идти? Если да, как бы вы это сделали?

Я не хочу передавать ссылку объекта MyGame объекту MyButton! Я думаю, что это не очень хороший способ решить эту проблему.

Я ценю любые предложения и помощь!

Приветствия

+0

Если вы посмотрите на [класс Button в java API] (http://docs.oracle.com/javase/7/docs/api/java/awt/Button.html), вы увидите, что есть функция с именем addActionListener. Быстрый поиск того, как использовать его в google, должен дать вам много информации, чтобы продолжить оттуда! – Gladhus

ответ

3

В конструкторе MyGame можно добавить ActionListener к btn, который будет вызываться, когда действие выполняется на кнопке.

btn.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     // Insert thing to do within MyGame here 
    } 
}); 
+0

Спасибо за хорошую идею! Помогает! – user3704589

1

Один из способов - сделать это наоборот (игра должна быть членом кнопки). Я знаю, что вы думаете, что «это не лучший способ решить эту проблему», но вы ошибаетесь, в этом нет ничего плохого.

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

public MyGame() { 
    btn.setOnAction(new EventHandler<ActionEvent>() { 
     public void handle(ActionEvent arg0) { doSomething(); } 
    }); 
} 
+0

Спасибо за интересную идею. Я, возможно, передумаю свою программу. Иногда речь идет о переосмыслении, чтобы сделать все :-) – user3704589

1

сделать «кнопку действия» интерфейс, который может быть передан в конструктор при создании MyButton. Пример:

public MyButton(final Runnable action) { 
    this.setOnAction(new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent arg0) { 
      action.run(); // POSSIBLE!!! 
     } 
    }); 
} 

или сохранить действие в поле MyButton например:

public MyButton(Runnable action) { 
    buttonAction = action;  // make buttonAction an instance field 
    this.setOnAction(new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent arg0) { 
      buttonAction.run(); 
     } 
    }); 
} 

Затем, когда MyGame создает новый MyButton, то MyGame получает сказать кнопку, что делать при нажатии на кнопку:

MyButton btn = new MyButton(new Runnable() { 
    @Override 
    public void run() { 
     MyGame.this.doSomething(); 
    } 
} 

или в Java 8:

MyButton btn = new MyButton(this::doSomething); 

ПРИМЕЧАНИЕ: Я еще не проверил это. Я думаю, что я правильно понял синтаксис, но я, возможно, допустил ошибку. Возможно, вам нужно назначить btn в конструкторе MyGame, а не в выражении инициализатора.

Это обобщенный подход (инъекция зависимостей?), Который работает во многих ситуациях. Могут быть другие решения, специфичные для Button (или других компонентов Swing, для которых уже установлен механизм прослушивания). Но этот механизм уменьшает сцепление, потому что MyButton действительно не нуждается в знании о том, кто его создал, и MyGame не должен знать, что планирует делать с действием Runnable. Некоторые другие возможные решения включают в себя наличие MyGame, выполняющего некоторую работу MyButton, что увеличивает сцепление.

+0

Что означает это «здесь» в новом анонимном классе MyButton (новый Runnable)? – dragon66

+1

@ dragon66 Он должен был быть 'MyGame.this' - спасибо, что поймал это. Я еще не тестировал свой код. (Я подозреваю, что 'MyGame.this' на самом деле не нужен, и он все равно найдет' doSomething() 'во внешнем классе.) – ajb

+0

Этот ответ действительно чрезмерен. Вам не нужна такая сложность. Посмотрите на ответ Оли, намного проще. – Crembo

Смежные вопросы