我想以有意義的方式使用Swing將MVC設計應用於我的Java應用程序。因此我的問題是,控制器如何在Java Swing中構造?Java Swing中的控制器是什麼?
我心裏有兩個選擇:
- 每個組件監聽器是一個自己的類,作爲控制器封裝的一部分
- 每個組件監聽器視圖包,它代表了調用內部的匿名類一個帶控制器方法的類。
既可能嗎?這是一個偏好問題,還是它有明確的定義?
我想以有意義的方式使用Swing將MVC設計應用於我的Java應用程序。因此我的問題是,控制器如何在Java Swing中構造?Java Swing中的控制器是什麼?
我心裏有兩個選擇:
既可能嗎?這是一個偏好問題,還是它有明確的定義?
控制器構成組件接口的另一半 ,主要是 交互的一半。控制器需要 保護鼠標和鍵盤事件。
在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
}
型號
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();
}
}
http://www.leepoint.net/notes-java/GUI/structure/40mvc.html – 2014-03-20 08:55:10
我心裏有兩個選擇:
- 每個組件監聽器是一個自己的類,如控制器 包
- 每個組件監聽器的一部分,是認爲 封裝內部的匿名類使用控制器方法將其呼叫委託給 類。是否可以使用 ?
是都可以,但我更喜歡寫單類,它實現了所有actionListioner並分配相同的所有組件在您的應用程序。通過這種方式,您可以在單點上跟蹤應用中的所有操作。 也可以用這種方法使您的視圖與控制器區分開來。
對於視圖和控制器能夠清晰的分離,你可以做這樣的:
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() {
// ...
}
}
}
現在我們可以實現不同的控制器可能是方便,如果我們要使用查看不同模型的組件。該控制器是實際視圖實例的策略。
在大多數情況下,將偵聽器定義爲匿名類就足夠了,因爲他們通常只是在控制器實例上調用方法。我通常使用監聽器作爲簡單的調度器 - 他們收到通知並將消息發送到另一個對象。一個監聽者類應該實現太多的業務邏輯,這超出了它的責任。
看看這個MVC architecture
Platzhirsch,
好傢伙,這是一個SERIOUSLY重量級的問題......其中一個沒有人會在論壇帖子中充分回答。這個artice Java SE Application Design With MVC由Robert Eckstein(Java神之一)詳細討論了這個問題。個人而言,我最終使用MVC的「變體」,我稱之爲MBVC(模型業務視圖控制器),它實際上非常接近MVVMC ... MVVM廣泛用於.NET循環;添加一個對我有意義的控制器,因爲我有一些Web MVC的經驗。我希望在閱讀上面的文章之前,我會介紹MVC-ise我的應用程序。你仍然可以在Sun的(現在是甲骨文的)Java論壇上閱讀我相當困惑的帖子。
乾杯。基思。
該視圖將包含GUI設計。視圖的actionPerformed方法應標識事件,並根據事件調用ControllerInterface上的各個方法。控制器的實現將實現這個ControllerInterface,並且在這裏實現由視圖調用的方法。這些方法可能會以某種方式與模型進行交互。模型本身將有一種方法來註冊觀察者(在這種情況下,視圖,順便說一下,甚至控制器都可以註冊),並且每次模型更改時都會更新觀察者。這基本上就是你如何構建應用程序。有關MVC的詳細信息,你也可以參考: here!
雖然搖擺框架已經實現了MVC的形式(顯性模型; JXyz & UI類=控制器&視圖),這種嚴格的分離應用很少使用水平,看起來很奇怪。
首先,我建議遵循以下設計:
如果您想更進一步,請使用NetBeans平臺等RCP(非常推薦)。
另請參閱此[答案](http://stackoverflow.com/questions/3066590/gui-problem-after-rewriting-to-mvc/3072979#3072979)。 – trashgod 2011-04-29 11:28:39
請注意,MVC可能適用於低級組件(例如JTextField),但在應用程序級別,其他模式通常更好;想到2種模式:MVP和PresentationModel(我稱之爲第二種模式MVPM,但這不是官方術語)。 – jfpoilpret 2011-04-29 11:50:41