我试图了解如何在我的 Java 应用程序中实现 MVC,阅读一些教程和 MVC hello worlds,但我仍然不确定很多事情,所以如果你能帮助我理解这一切,我会很高兴。
假设我有一个简单的 GUI 应用程序,用于存储和处理各种建筑物。我可以通过从列表中选择类型并按下按钮来添加建筑物。这些建筑物将存储在一些数组列表中,显示在 GUI 中并且可以编辑(房间数,楼层数......不重要)。建筑物将显示在 JComboBox 中,选择某个建筑物后,将出现该建筑物的设置面板。
到目前为止,我有 2 个“组件”。建筑物(集装箱)和建筑物。我创建了BuildingsModel类,它包含建筑物,有一些方法可以使用它们并在更改后通知观察者。然后我有一个BuildingsView类,它正在观察 BuildingsModel。然后我有BuldingsController类,它带有构造函数方法,它将 BuildingsModel 和 BuildingsView 作为参数,将视图绑定到模型作为观察者,创建一些初始建筑物并向视图添加一些侦听器。
现在我不知道如何继续。有几件事情我不是很高兴。
我已将侦听器绑定到按钮,它将从视图中的 JList 中获取当前选择,创建新对象(xxxBuildingModel)并将其添加到 BuildingsModel。然而,JList 只包含所有建筑类型的字符串表示,为了避免长 if-else 语句并为该字符串找到正确的类,我不得不使用反射。(每种建筑类型都有自己的扩展BuildingModel的类。)有没有更好的方法呢?
第二个侦听器绑定到包含已创建的构建实例的 JComboBox。在该组合框中选择建筑物后,我想显示该建筑物的设置表单。所以我想应该有一些与 BuildingModel 关联的视图类,它将显示其当前设置(模型的状态)。但我不确定,如何从 BuildingsController 的构造函数上下文中做到这一点。我只能访问建筑物的模型,那么我应该如何“找到”该实例的正确视图并显示它?也许我做错了,组合框不应该只包含模型,而是控制器(可以访问模型和视图),在这种情况下,我可以调用控制器的视图方法,该方法将从模型中获取所需的数据,传递它以查看和显示它。我不
这是代码中最重要的部分。我没有包含 BuildingModel 类及其子类,因为现在它们只是带有 toString() 方法的空白类。
public class BuildingsController {
public BuildingsController(final BuildingsModel model, final BuildingsView view) {
class addBuildingButtonActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String selectedBuildingType;
if ((selectedBuildingType = view.getSelectedBuildingType()) != null) {
try {
BuildingModel newBuilding = (BuildingModel) Class.forName("building.models." + selectedBuildingType + "BuildingModel").newInstance();
model.addBuilding(newBuilding);
} catch (InstantiationException ex) {
//addToErrorLog
} catch (IllegalAccessException ex) {
//addToErrorLog
} catch (ClassNotFoundException ex) {
//addToErrorLog
}
} else {
//addToLog - NO_BUILDING_SELECTED
}
}
}
class buildingComboBoxSelectListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
BuildingModel selectedBuilding;
if ((selectedBuilding = view.getSelectedBuilding()) != null) {
//display current building form???
}
}
}
model.addObserver(view);
model.addBuilding(new HospitalBuildingModel());
model.addBuilding(new SchoolBuildingModel());
view.fillBuildingTypesList(BuildingsModel.getAllBuildingsTypes());
view.addAddBuildingButtonListener(new addBuildingButtonActionListener());
view.addActiveBuildingsListener(new buildingComboBoxSelectListener());
}
}
public class BuildingsModel extends Observable {
private static String[] allBuildingsTypes = {"School", "Hospital", "Stadion"};
private ArrayList<BuildingModel> buildings = new ArrayList<BuildingModel>();
public void addBuilding(BuildingModel building){
this.buildings.add(building);
this.setChanged();
this.notifyObservers();
}
public BuildingModel[] getAllBuildings(){
return this.buildings.toArray(new BuildingModel[this.buildings.size()]);
}
public static String[] getAllBuildingsTypes(){
return BuildingsModel.allBuildingsTypes;
}
}
public class BuildingsView implements Observer {
private static String name = "Buldings";
private static String addBuildingButtonText = "Add building";
private JComboBox allActiveBuildings = new JComboBox();
private JList buildingTypesList = new JList();
private JButton addBuildingButton = new JButton(BuildingsView.addBuildingButtonText);
@Override
public void update(Observable model, Object o){
BuildingModel[] allBuildings = ((BuildingsModel) model).getAllBuildings();
this.allActiveBuildings.removeAllItems();
for(BuildingModel building : allBuildings){
this.allActiveBuildings.addItem(building);
}
}
public String getSelectedBuildingType(){
return (String) this.buildingTypesList.getSelectedValue();
}
public BuildingModel getSelectedBuilding(){
return (BuildingModel) this.allActiveBuildings.getSelectedItem();
}
public void fillBuildingTypesList(String[] buildingTypes){
this.buildingTypesList.setListData(buildingTypes);
}
public void addAddBuildingButtonListener(ActionListener l){
this.addBuildingButton.addActionListener(l);
}
public void addActiveBuildingsListener(ActionListener l){
this.allActiveBuildings.addActionListener(l);
}
public JComponent display(){
JPanel panel = new JPanel();
Border border = BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(BuildingsView.name), BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.setBorder(border);
panel.add(this.allActiveBuildings);
panel.add(this.buildingTypesList);
panel.add(this.addBuildingButton);
panel.setPreferredSize(new Dimension(200, 262));
return panel;
}
}
主要的:
public static void main(String[] args) {
BuildingsView buildingsView = new BuildingsView();
BuildingsModel buildingsModel = new BuildingsModel();
BuildingsController buldingsController = new BuildingsController(buildingsModel, buildingsView);
mainWindow window = new mainWindow("MVC test", buildingsView);
window.generateDefaultLayout();
window.showMainWindow();
}
窗户:
public class mainWindow extends JFrame {
private JPanel buildingsPanel = new JPanel();
private BuildingsView buildingsView;
public mainWindow(String title, BuildingsView buildingsView) {
this.buildingsView = buildingsView;
this.setTitle(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void generateDefaultLayout(){
this.setLayout(new FlowLayout());
this.setPreferredSize(new Dimension(1200, 920));
this.addBuildingsPanel();
}
public void addBuildingsPanel(){
this.buildingsPanel.add(this.buildingsView.display());
this.add(this.buildingsPanel);
}
public void showMainWindow(){
this.pack();
this.setVisible(true);
}
}
谢谢 :)