Подтвердить что ты не робот

Что такое контроллер в Java Swing?

Я хотел бы применить проект MVC к моему Java-приложению с помощью Swing значимым образом. Поэтому мой вопрос заключается в том, как контроллеры будут структурированы в Java Swing?

У меня есть два варианта:

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

Возможно ли это? Это вопрос предпочтения, или он четко определен?

4b9b3361

Ответ 1

Контроллер составляет вторую половину интерфейса компонента, в основном половина взаимодействия. Контроллер принимает уход за событиями мыши и клавиатуры.

в компонентах Swing, таких как JButton и т.д., являются контроллерами. и все классы слушателей перенаправляют события на модель, имеющую вашу бизнес-логику.

пример:

основная программа

import javax.swing.*;

public class CalcMVC {
    //... Create model, view, and controller.  They are
    //    created once here and passed to the parts that
    //    need them so there is only one copy of each.
    public static void main(String[] args) {

        CalcModel      model      = new CalcModel();
        CalcView       view       = new CalcView(model);
        CalcController controller = new CalcController(model, view);

        view.setVisible(true);
    }
}

Просмотр

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

class CalcView extends JFrame {
    //... Constants
    private static final String INITIAL_VALUE = "1";

    //... Components
    private JTextField m_userInputTf = new JTextField(5);
    private JTextField m_totalTf     = new JTextField(20);
    private JButton    m_multiplyBtn = new JButton("Multiply");
    private JButton    m_clearBtn    = new JButton("Clear");

    private CalcModel m_model;

    //======================================================= constructor
    /** Constructor */
    CalcView(CalcModel model) {
        //... Set up the logic
        m_model = model;
        m_model.setValue(INITIAL_VALUE);

        //... Initialize components
        m_totalTf.setText(m_model.getValue());
        m_totalTf.setEditable(false);

        //... Layout the components.      
        JPanel content = new JPanel();
        content.setLayout(new FlowLayout());
        content.add(new JLabel("Input"));
        content.add(m_userInputTf);
        content.add(m_multiplyBtn);
        content.add(new JLabel("Total"));
        content.add(m_totalTf);
        content.add(m_clearBtn);

        //... finalize layout
        this.setContentPane(content);
        this.pack();

        this.setTitle("Simple Calc - MVC");
        // The window closing event should probably be passed to the 
        // Controller in a real program, but this is a short example.
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    void reset() {
        m_totalTf.setText(INITIAL_VALUE);
    }

    String getUserInput() {
        return m_userInputTf.getText();
    }

    void setTotal(String newTotal) {
        m_totalTf.setText(newTotal);
    }

    void showError(String errMessage) {
        JOptionPane.showMessageDialog(this, errMessage);
    }

    void addMultiplyListener(ActionListener mal) {
        m_multiplyBtn.addActionListener(mal);
    }

    void addClearListener(ActionListener cal) {
        m_clearBtn.addActionListener(cal);
    }
}

контроллер

import java.awt.event.*;

public class CalcController {
    //... The Controller needs to interact with both the Model and View.
    private CalcModel m_model;
    private CalcView  m_view;

    //========================================================== constructor
    /** Constructor */
    CalcController(CalcModel model, CalcView view) {
        m_model = model;
        m_view  = view;

        //... Add listeners to the view.
        view.addMultiplyListener(new MultiplyListener());
        view.addClearListener(new ClearListener());
    }


    ////////////////////////////////////////// inner class MultiplyListener
    /** When a mulitplication is requested.
     *  1. Get the user input number from the View.
     *  2. Call the model to mulitply by this number.
     *  3. Get the result from the Model.
     *  4. Tell the View to display the result.
     * If there was an error, tell the View to display it.
     */
    class MultiplyListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            String userInput = "";
            try {
                userInput = m_view.getUserInput();
                m_model.multiplyBy(userInput);
                m_view.setTotal(m_model.getValue());

            } catch (NumberFormatException nfex) {
                m_view.showError("Bad input: '" + userInput + "'");
            }
        }
    }//end inner class MultiplyListener


    //////////////////////////////////////////// inner class ClearListener
    /**  1. Reset model.
     *   2. Reset View.
     */    
    class ClearListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            m_model.reset();
            m_view.reset();
        }
    }// end inner class ClearListener
}

Model

import java.math.BigInteger;

public class CalcModel {
    //... Constants
    private static final String INITIAL_VALUE = "0";

    //... Member variable defining state of calculator.
    private BigInteger m_total;  // The total current value state.

    //============================================================== constructor
    /** Constructor */
    CalcModel() {
        reset();
    }

    //==================================================================== reset
    /** Reset to initial value. */
    public void reset() {
        m_total = new BigInteger(INITIAL_VALUE);
    }

    //=============================================================== multiplyBy
    /** Multiply current total by a number.
    *@param operand Number (as string) to multiply total by.
    */
    public void multiplyBy(String operand) {
        m_total = m_total.multiply(new BigInteger(operand));
    }

    //================================================================= setValue
    /** Set the total value. 
    *@param value New value that should be used for the calculator total. 
    */
    public void setValue(String value) {
        m_total = new BigInteger(value);
    }

    //================================================================= getValue
    /** Return current calculator total. */
    public String getValue() {
        return m_total.toString();
    }
}

Ответ 2

Platzhirsch,

Чувак, это тяжелый вопрос СЕРЬЕЗНО... тот, на который никто не будет отвечать адекватно на форуме. Эта статья arta Java SE Application Design с MVC от Роберт Экштейн (один из богов Java) обсуждает проблему на длина.

Лично я закончил использование "варианта" MVC, который я назвал MBVC (Model Business View Controller), который фактически близок к MVVMC. MVVM широко используется в .NET cirles; добавив, что контроллер имеет смысл для меня, поскольку у меня был опыт работы с несколькими MVC. Хотелось бы, чтобы я прочитал вышеприведенную статью, прежде чем я придумал MVC-ise мое приложение. Вы все еще можете прочитать мои довольно озадаченные сообщения на форумах Sun (теперь Oracle) Java.

Приветствия. Кит.

Ответ 3

В то время как среда Swing уже реализует форму MVC (явные модели, классы JXyz и UI = контроллер и представление), это строгое разделение редко используется на уровне приложения и выглядит довольно странно.

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

  • реализовать бизнес-логику на стороне клиента с помощью POJO
  • оберните POJO с помощью настраиваемых моделей Swing, где это необходимо (ListModel, TableModel)
  • Используйте GUI-конструктор для создания графического интерфейса
  • Используйте шаблон "Посредник" для прослушивания событий (пользовательский родительский JPanel прослушивает события своих дочерних элементов и обновляет другие дочерние элементы или при необходимости запускает собственные события)

Если вы хотите сделать еще один шаг, используйте RCP, например платформу NetBeans (очень рекомендуется).

Ответ 5

Вид будет охватывать дизайн графического интерфейса. Метод actionPerformed представления должен идентифицировать событие и вызывать соответствующие методы на ControllerInterface в зависимости от события. Реализация контроллера будет реализовывать этот ControllerInterface, и здесь будут реализованы методы, вызываемые представлением. Эти методы предположительно будут взаимодействовать с моделью каким-либо образом. Сама модель будет иметь возможность регистрировать наблюдателей (представление в этом случае, кстати, даже регистраторы могут быть зарегистрированы) и обновлять наблюдателей каждый раз, когда изменяется модель. Это, по сути, то, как вы структурируете свое приложение. Для получения дополнительной информации о MVC вы также можете обратиться к: здесь!

Ответ 6

У меня есть два варианта:

  • Каждый компонент-слушатель - это собственный класс, как часть контроллера пакет
  • Каждый компонентный прослушиватель является анонимным классом внутри представления пакет, который делегирует свой призыв к класс с методами контроллера. Это оба возможно?

Да, оба возможны, но я предпочитаю писать класс Single, который реализует все actionListioner и присваивает то же самое всем компоненту вашего приложения. Таким образом, вы можете отслеживать все действия в приложении в одной точке. Также вы можете сделать свое представление отличным от контроллера.

Ответ 7

Для четкого разделения View и Controller вы можете сделать это следующим образом:

public class MyView extends SomeSwingComponent {

   private Controller controller;
   public View(Controller controller) {
     this.controller = controller;
     JButton saveButton = new JButton("Save");
     button.addActionListner(controller.getSaveButtonListener());
   }
}

public class MyController implements Controller {
  private ActionListener saveButtonListener;
  @Override
  public ActionListener getSaveButtonListener() {
    if (saveButtonListener == null) {
      saveButtonListener = new ActionListener() {
        // ...
      }
  }
}

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

В большинстве случаев достаточно определить слушателей как анонимные классы, потому что они обычно просто вызывают метод на экземпляре контроллера. Обычно я использую слушателей как простых диспетчеров - они получают уведомление и отправляют сообщение другому объекту. Класс слушателя должен реализовывать слишком много бизнес-логики, что выходит за рамки его обязанностей.