Java アプリケーションに MVC を実装する方法を理解しようとしており、いくつかのチュートリアルと MVC の hello world を読んでいますが、まだ多くのことがわかりません。これらすべてを理解するのを手伝っていただければ幸いです。
さまざまな建物の保存と操作に使用される単純な GUI アプリケーションがあるとします。リストからタイプを選択してボタンを押すと、建物を追加できます。これらのビルディングはいくつかのアレイリストに保存され、GUI に表示され、編集可能になります (部屋の数、フロアの数 ..... 重要ではありません)。建物がJComboBoxに表示され、建物を選択すると、その建物の設定パネルが表示されます。
これまでのところ、2つの「コンポーネント」があります。建物(コンテナ)と建物。BuildingsModelクラスを作成しました。これは建物を保持し、それらを操作するメソッドをいくつか持ち、変更後にオブザーバーに通知します。それから、 BuildingsModel を監視するBuildingsViewクラスがあります。次に、BuildingsModel と BuildingsView をパラメーターとして取り、ビューをオブザーバーとしてモデルにバインドし、いくつかの初期建物を作成し、いくつかのリスナーをビューに追加する、コンストラクター メソッドだけを持つBuldingsControllerクラスを用意します。
今、私は続ける方法がわかりません。あまり嬉しくない点がいくつかあります。
リスナーをボタンにバインドしました。これにより、ビュー内の JList から現在の選択が取得され、新しいオブジェクト (xxxBuildingModel) が作成され、BuildingsModel に追加されます。ただし、JList には、すべてのビルド タイプの文字列表現のみが含まれており、長い if-else ステートメントを回避し、その文字列に適したクラスを見つけるために、リフレクションを使用する必要がありました。(各建物の種類には、 BuildingModelを拡張する独自のクラスがあります。)それを行うより良い方法はありますか?
2 番目のリスナーは、作成済みの構築インスタンスを含む 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);
}
}
ありがとう :)