当我开始一个复杂的MVC Swing应用程序时,我也遇到了那些“意大利面条”.
以下是我管理它的方式.但这是我自己的方式,也许你不同意我的看法!
如果有人不同意我的任何言论,请告诉我.我不是专业人士,只是想帮忙. 🙂
提醒
首先,’Boris The Spider’已经为您介绍了良好的MVC / MVP原则.我会记住你的基础:
这意味着您的控制器需要直接访问模型和查看对象.视图可以访问模型对象.该模型单独工作.这意味着如果您更改模型(更改所使用的API,更改算法,……),视图并不关心,它只是通过几种方法显示它.
控制器必须监听用户操作(按钮,字段等)并根据此更改模型数据.
该视图仅能够显示模型中的数据.没有其他的.
如何实施
实例化对象
首先,我创建模型和视图对象.
public static void main(String[] args) {
EntityManager entManager = new EntityManager();
Map mapView = new Map(entManager);
}
您可以创建对象,通过构造函数参数传递每个对象所需的引用.该模型始终是第一个创建的,因为它是独立的.
然后,创建视图,该模型需要模型来获取数据值.
在创建所有GUI对象后,我在视图中创建控制器.这样,我在方法attachListeners()中将它们附加到它们的监听器.
绘图实体
我的方法是视图需要每个实体类型的方法.例如drawCity()方法,然后是drawRoad()ordrawOilStation().因为视图是唯一必须知道如何绘制它们的对象.模型不必处理它.
因为你的例子需要绘制所有组件,所以paintComponents()方法会非常混乱,是的.在我看来,你的“方法1”是最好的方法.
06001
让我们假设你有一个带有一些JList和JPanel的GUI.您的加载方法(读取从模型中显示的数据)将单独调用,每个方法从模型中获取所需的数据.
例如 :
public void createInterface(){
//Instanciate some Swing components
fillPhoneList();
updateNamePanel();
}
private void fillPhoneList(){
List phoneList = model.getPhoneList();
for(PhoneNumber phone : phoneList){
phoneListView.add(phone);
}
}
更新视图
1)从用户操作更改视图
通常,控制器在出现界面事件时作出反应.控制器的工作是告诉模型改变,同时更新调用“加载”方法的视图.
假设您有2个视图,Map和EntityDetails.你有一个控制器,称为MapListener和EntityDetailsController.它们都具有相应的视图对象作为属性.他们从那里查看所有用户操作.
public class MapListener implements ActionListener{
private Map mapView;
@Override
public void actionPerformed(ActionEvent e){
//Doing some things
}
}
public class EntityDetailsListener implements ActionListener{
private EntityDetails entityView;
@Override
public void actionPerformed(ActionEvent e){
//Doing some things
}
}
我经常做的事情是在辅助视图中添加对主视图的引用.我的意思是Map是主框架,它有时会显示第二个视图EntityDetails.所以我在EntityDetailsListener中添加了对Map的引用,当然有必要.
public class EntityDetailsListener implements ActionListener{
private EntityDetails entityView;
private Map mapView;
@Override
public void actionPerformed(ActionEvent e){
//Doing some things
if (e.getSource() == changeNameButton){
//For exemple, if you change the name of the entity on the EntityDetails view.
mapView.updateEntity(this); //calling the update method in the Map class.
}
}
}
2)模型自动转换
当您的模型自行更改时,必须通知您的视图.您的控制器位于它们之间,是从模型接收通知的对象,说“嘿,我改变了,让我们更新视图!”
这就是你应该在Model对象中编写一些fireXXXChange()方法的原因.他们会告诉听众他们必须做一些工作.
因此,您需要将侦听器传递给模型对象.因为您在其他任何事情之前创建它,所以必须通过addMapListener(MapListener listener)之类的方法传递它.然后,您可以在数据更改时通知此控制器.
因为公开起来非常复杂,所以我只是在how to manage MVC with Swing上给你这个Oracle教程.
我真的希望它不会混淆,我帮助了你一点点!
解决意大利面条代码的最佳方法是记录并查看编码所需的每个应用程序的最佳方法,因为每种情况都不同.