Java ActionListeners для автономных классов

Есть ли способ переместить классы actionListener в автономные классы?

Я сделал пример, используя шаблон проектирования Java и MVC. У меня есть 3 кнопки, которые меняют цвет фона.

Вот модель

public class ChangeFontColorApplicationModel {
    public ChangeFontColorApplicationModel(){}
}

Вид

import java.awt.event.*;
import javax.swing.*;

public class ChangeFontColorApplicationView extends JFrame{
private JButton changeToYellowButton = new JButton("Yellow font");
private JButton changeToBlackButton = new JButton("Black font");
private JButton changeToBlueButton = new JButton("Blue font");

public ChangeFontColorApplicationView(){
    super("Change font");
    JPanel buttonPanel = new JPanel();

    buttonPanel.add(changeToYellowButton);
    buttonPanel.add(changeToBlackButton);
    buttonPanel.add(changeToBlueButton);

    this.add(buttonPanel);
}

public void addButtonActionListener(){
    changeToYellowButton.addActionListener(new yellowBackgroundHandler());
    changeToBlackButton.addActionListener(new yellowBackgroundHandler());
    changeToBlueButton.addActionListener(new yellowBackgroundHandler());
}
}

Контроллер

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ChangeFontColorApplicationController {
private ChangeFontColorApplicationView changeFontColorApplicationViewObject;
backgroundHandler yellowBackgroundHandlerObject = new yellowBackgroundHandler();
backgroundHandler blackBackgroundHandlerObject = new blackBackgroundHandler();
backgroundHandler blueBackgroundHandlerObject = new blueBackgroundHandler();

public ChangeFontColorApplicationController(ChangeFontColorApplicationView changeFontColorApplicationViewObject){
    this.changeFontColorApplicationViewObject = changeFontColorApplicationViewObject;

    yellowBackgroundHandlerObject.setNextHandlerInChain(blackBackgroundHandlerObject);
    blackBackgroundHandlerObject.setNextHandlerInChain(blueBackgroundHandlerObject);

    this.changeFontColorApplicationViewObject.addButtonActionListener();
}
}

Теперь я создал интерфейс, который обрабатывает события кнопок.

public interface backgroundHandler extends ActionListener{
public void setNextHandlerInChain(backgroundHandler nextInChain);
public void handleCommand(String getActionCommandString);
public void actionPerformed(ActionEvent event);
}

Каждый класс, реализующий интерфейсы, обрабатывает ActionEvent. Если он не может, он переходит к следующему классу (как цепочка ответственности)

обработчик желтого шрифта

import java.awt.Color;
import java.awt.event.ActionEvent;

public class yellowBackgroundHandler implements backgroundHandler{
private backgroundHandler nextInChain;
private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject = new ChangeFontColorApplicationView();

public yellowBackgroundHandler(){}

@Override
public void setNextHandlerInChain(backgroundHandler nextInChain) {
    this.nextInChain = nextInChain;
}

@Override
public void handleCommand(String getActionCommandString) {
    if(getActionCommandString.equalsIgnoreCase("Yellow font")){
        ChangeFontColorApplicationViewObject.setBackground(Color.yellow);
    }
    else {
        nextInChain.handleCommand(getActionCommandString);
    }
}

@Override
public void actionPerformed(ActionEvent event) {
    try{
        handleCommand(event.getActionCommand());
    }
    catch (Exception exeption){
        ChangeFontColorApplicationViewObject.setTitle(exeption.toString());            
    }
}
}

обработчик черного шрифта

import java.awt.Color;
import java.awt.event.ActionEvent;

public class blackBackgroundHandler implements backgroundHandler{
private backgroundHandler nextInChain;
private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject = new ChangeFontColorApplicationView();

public blackBackgroundHandler(){}

@Override
public void setNextHandlerInChain(backgroundHandler nextInChain) {
    this.nextInChain = nextInChain;
}

@Override
public void handleCommand(String getActionCommandString) {
    if(getActionCommandString.equalsIgnoreCase("Black font")){
        ChangeFontColorApplicationViewObject.setBackground(Color.BLACK);
    }
    else {
        nextInChain.handleCommand(getActionCommandString);
    }
}

@Override
public void actionPerformed(ActionEvent event) {
    try{
        handleCommand(event.getActionCommand());
    }
    catch (Exception exeption){
        ChangeFontColorApplicationViewObject.setTitle(exeption.toString());            
    }
}
}

обработчик синего шрифта

import java.awt.Color;
import java.awt.event.ActionEvent;

public class blueBackgroundHandler implements backgroundHandler{
private backgroundHandler nextInChain;
private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject = new ChangeFontColorApplicationView();

public blueBackgroundHandler(){}

@Override
public void setNextHandlerInChain(backgroundHandler nextInChain) {
    this.nextInChain = nextInChain;
}

@Override
public void handleCommand(String getActionCommandString) {
    if(getActionCommandString.equalsIgnoreCase("Μπλε φόντο")){
        ChangeFontColorApplicationViewObject.setBackground(Color.BLUE);
    }
    else {
        ChangeFontColorApplicationViewObject.setTitle("This is the back end of COR");
    }
}

@Override
public void actionPerformed(ActionEvent event) {
    try{
        handleCommand(event.getActionCommand());
    }
    catch (Exception exeption){
        ChangeFontColorApplicationViewObject.setTitle(exeption.toString());            
    }
}
}

Наконец, я создаю класс с основным методом

public class ChangeFontColorApp {
public static void main(String[] args){
    ChangeFontColorApplicationView changeFontColorApplicationViewObject = new ChangeFontColorApplicationView();
    ChangeFontColorApplicationController changeFontColorApplicationControllerObject = new ChangeFontColorApplicationController(changeFontColorApplicationViewObject);

    changeFontColorApplicationViewObject.setVisible(true);
    changeFontColorApplicationViewObject.setSize(600, 600);
       changeFontColorApplicationViewObject.setDefaultCloseOperation(ChangeFontColorApplicationView.EXIT_ON_CLOSE);
}
}

Есть ли способ заставить это работать? Я не хочу иметь внутренний класс для обработки событий с несколькими блоками if в нем. Любые предложения будут действительно оценены.


person Vassilis De    schedule 20.06.2014    source источник
comment
Прочтите Как создать минимальный, полный и проверяемый пример. Стены кода — это плохо. Никто не хочет все это читать.   -  person Scott Solmer    schedule 20.06.2014
comment
Да, вы можете написать класс контроллера действий. Ваш контроллер не обязательно должен быть одним классом. Классов может быть много, каждый отвечает на определенное действие. Взгляните на мою статью 2048 Game in Java Swing, чтобы увидеть один из способов использования MVC для создания приложения Java Swing.   -  person Gilbert Le Blanc    schedule 20.06.2014
comment
Хорошо, ребята, я прочитаю оба. Спасибо вам за ваши предложения   -  person Vassilis De    schedule 20.06.2014


Ответы (1)


Это не сработает. Но проблема не в том, что у вас есть автономные классы (можно использовать автономные классы). Скорее проблема в следующем:

В классе просмотра у вас есть:

public void addButtonActionListener(){
    changeToYellowButton.addActionListener(new yellowBackgroundHandler());
    changeToBlackButton.addActionListener(new yellowBackgroundHandler());
    changeToBlueButton.addActionListener(new yellowBackgroundHandler());
}

это означает, что нажатие всех кнопок обрабатывается yellowBackgroundHandler. Но yellowBackgroundHandler принимает клики только от changeToYellowButton. Кроме того, для yellowBackgroundHandler не настроен следующий обработчик.

Чтобы исправить это, в классе представления измените это:

public void addButtonActionListener(){
    changeToYellowButton.addActionListener(new yellowBackgroundHandler());
    changeToBlackButton.addActionListener(new yellowBackgroundHandler());
    changeToBlueButton.addActionListener(new yellowBackgroundHandler());
}

to

public void addButtonActionListener(backgroundHandler handler){
    changeToYellowButton.addActionListener(handler);
    changeToBlackButton.addActionListener(handler);
    changeToBlueButton.addActionListener(handler);
}

и в классе контроллера измените это:

this.changeFontColorApplicationViewObject.addButtonActionListener();

to

this.changeFontColorApplicationViewObject.addButtonActionListener(yellowBackgroundHandlerObject);

Еще одна проблема, которую я вижу, заключается в том, что yellowBackgroundHandler, blackBackgroundHandler и blueBackgroundHandler имеют закрытую переменную ChangeFontColorApplicationViewObject, которая указывает на собственный экземпляр ChangeFontColorApplicationView. Нам нужна эта переменная, чтобы указать на экземпляр, созданный в основном методе. Для этого измените это:

private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject = new ChangeFontColorApplicationView();
public blueBackgroundHandler(){}

to:

private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject;
public blueBackgroundHandler(ChangeFontColorApplicationView ChangeFontColorApplicationViewObject){
  this.ChangeFontColorApplicationViewObject = ChangeFontColorApplicationViewObject;
}

и измените это:

private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject = new ChangeFontColorApplicationView();
public blackBackgroundHandler(){}

to:

private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject;
public blackBackgroundHandler(ChangeFontColorApplicationView ChangeFontColorApplicationViewObject){
  this.ChangeFontColorApplicationViewObject = ChangeFontColorApplicationViewObject;
}

и измените это:

private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject = new ChangeFontColorApplicationView();
public blueBackgroundHandler(){}

to:

private ChangeFontColorApplicationView ChangeFontColorApplicationViewObject;
public blueBackgroundHandler(ChangeFontColorApplicationView ChangeFontColorApplicationViewObject){
  this.ChangeFontColorApplicationViewObject = ChangeFontColorApplicationViewObject;
}

наконец, измените это:

backgroundHandler yellowBackgroundHandlerObject = new yellowBackgroundHandler();
backgroundHandler blackBackgroundHandlerObject = new blackBackgroundHandler();
backgroundHandler blueBackgroundHandlerObject = new blueBackgroundHandler();

public ChangeFontColorApplicationController(ChangeFontColorApplicationView changeFontColorApplicationViewObject){
    this.changeFontColorApplicationViewObject = changeFontColorApplicationViewObject;

    yellowBackgroundHandlerObject.setNextHandlerInChain(blackBackgroundHandlerObject);
    blackBackgroundHandlerObject.setNextHandlerInChain(blueBackgroundHandlerObject);

    this.changeFontColorApplicationViewObject.addButtonActionListener();
}

to

backgroundHandler yellowBackgroundHandlerObject = new yellowBackgroundHandler();
backgroundHandler blackBackgroundHandlerObject = new blackBackgroundHandler();
backgroundHandler blueBackgroundHandlerObject = new blueBackgroundHandler();

public ChangeFontColorApplicationController(ChangeFontColorApplicationView changeFontColorApplicationViewObject){
    this.changeFontColorApplicationViewObject = changeFontColorApplicationViewObject;
    this.yellowBackgroundHandlerObject = new yellowBackgroundHandler(this.changeFontColorApplicationViewObject);
    this.blackBackgroundHandlerObject = new blackBackgroundHandler(this.changeFontColorApplicationViewObject);
    this.blueBackgroundHandlerObject = new blueBackgroundHandler(this.changeFontColorApplicationViewObject);

    yellowBackgroundHandlerObject.setNextHandlerInChain(blackBackgroundHandlerObject);
    blackBackgroundHandlerObject.setNextHandlerInChain(blueBackgroundHandlerObject);

    this.changeFontColorApplicationViewObject.addButtonActionListener(this.changeFontColorApplicationViewObject);
}
person fajarkoe    schedule 20.06.2014
comment
Боюсь, это тоже не сработало ... может быть, это из-за добавления actionListeners в контроллер, а не в поле зрения, перед добавлением кнопок в buttonPanel? - person Vassilis De; 20.06.2014
comment
Возможно, вы можете подробнее рассказать о не сработало? Желтая кнопка работает? - person fajarkoe; 20.06.2014
comment
Нет, не... Чтобы быть более конкретным, я обнаружил, что событие застревает в цикле while в методе EventDispatchThread.java, pumpEventsForFilter. Находясь в цикле, отладка просто остается там. Я не могу перешагнуть дальше. Как будто он не может выйти из цикла while и останавливает отладку. Что это может быть? Это одинаково для каждой кнопки. - person Vassilis De; 20.06.2014
comment
Я нашел еще одну проблему. Я только что обновил ответ. Дайте мне знать, как это происходит. - person fajarkoe; 20.06.2014
comment
В последнем выражении this.changeFontColorApplicationViewObject.addButtonActionListener(this.changeFontColorApplicationViewObject); метод addButtonActionListener() принимает аргумент backgroundHandler. Как я должен бросить это? И еще: Утверждения backgroundHandler yellowBackgroundHandlerObject = new yellowBackgroundHandler(); backgroundHandler blackBackgroundHandlerObject = new blackBackgroundHandler(); backgroundHandler blueBackgroundHandlerObject = new blueBackgroundHandler(); не должны отличаться? Теперь их конструктор принимает аргумент. - person Vassilis De; 20.06.2014
comment
Извините, последняя строка должна быть this.changeFontColorApplicationViewObject.addButtonActionListener(this.yellowBackgroundHandlerObject); - person fajarkoe; 21.06.2014
comment
Я пытался запустить его так, как вы сказали, но он выдавал исключения в main из-за вызова пустого конструктора в backgroundHandler [color]BackgroundHandlerObject = new [color]BackgroundHandler();statements. Поэтому я внес некоторые изменения в контроллер, чтобы он работал правильно backgroundHandler yellowBackgroundHandlerObject;//... и внутри конструктора this.yellowBackgroundHandlerObject = new yellowBackgroundHandler(this.changeFontColorApplicationViewObject);//and so for blue and black background handler} Приложение запускается, но кнопки все равно не работают.. - person Vassilis De; 21.06.2014
comment
Я нашел проблему. Мне просто нужно было установить макет в контейнер. Теперь все работает. Большое спасибо за Вашу помощь - person Vassilis De; 26.06.2014