Problema MVC in Java project

di il
2 risposte

Problema MVC in Java project

Salve a tutti ragazzi.
Vi scrivo perchè ho un problema per quanto riguarda un progetto che sto eseguendo con due compagni di corso. Stiamo sviluppando un simulatore di un Sistema solare. Stiamo adottando il pattern MVC (io gestisco la parte del controller) e sono bloccato sulla funzione update, la quale cattura un Evento (input dall'utente) ed esegue le dovute funzioni. Il fatto è che questo metodo a seconda dell'evento dovrebbe accettare input diversi.
Esempio: se l'utente volesse salvare/caricare una configurazione, il metodo update dovrebbe ricevere il tipo di evento che specifica quell'azione e una stringa che identifica la directory dove si vuole salvare/caricare il file, mentre invece se l'utente volesse aggiungere un corpo celeste lo stesso metodo dovrebbe ricevere il tipo di evento che specifica quell'azione e le coordinate dove deve essere "posizionato" (ovviamente sono presenti tante altre funzioni, le quali richiedono svariati input).
In pratica renderei la view indipendente dal controller, chiamando lo stesso metodo per ogni evento... il problema è che non so come implementare questo metodo, che riceve input diversi.

Spero di essere stato chiaro, grazie della disponibilità
Andrea

2 Risposte

  • Re: Problema MVC in Java project

    Bonda ha scritto:


    il problema è che non so come implementare questo metodo, che riceve input diversi.
    Con così poco è abbastanza improbabile riuscire a darti indicazioni più utili. Che tipologia di applicazione è? (desktop? webapp?) Cosa usa per la presentazione? Come hai strutturato le classi? Cosa hai scritto esattamente?
  • Re: Problema MVC in Java project

    andbin ha scritto:


    Bonda ha scritto:


    il problema è che non so come implementare questo metodo, che riceve input diversi.
    Con così poco è abbastanza improbabile riuscire a darti indicazioni più utili. Che tipologia di applicazione è? (desktop? webapp?) Cosa usa per la presentazione? Come hai strutturato le classi? Cosa hai scritto esattamente?
    Allora: è un'applicazione dekstop e abbiamo utilizzato le librerie di JavaFX.
    Per quanto riguarda le classi:
    Qui ho riassunto i "punti salienti" della view in relazione al problema. Come potete notare, per ogni pulsante chiamo direttamente il metodo nel controller (es c.zoomUp).
    package atlas.view;
    
    public class ViewImpl extends Application implements View {
    
        Map<String, ImageView> planet_map = new HashMap<>();
        Map<String, Button> button_map = new HashMap<>();
        double x, y;
        BorderPane rootPane = new BorderPane();
        Pane root1 = new Pane();
        Controller c;
        double posy = 1;
        boolean bool = true;
        double unit = 0.0;
    
        public void start(Stage primaryStage) {
    
            c = ControllerImpl.getIstanceOf();
            c.setView(this);
            Button play = new Button("Play");
            Button pause = new Button("Pause");
            Label zoomLabel = new Label("Zoom");
            Button zoomUp = new Button("+");
            Button zoomDown = new Button("-");
    
            // Inserisco i pulsanti nella mappa
            button_map.put(play.getText(), play);
            button_map.put(pause.getText(), pause);
            button_map.put(zoomUp.getText(), zoomUp);
            
            // Setto i pulsanti
            play.setOnAction(e -> {
                c.startSim();
            });
    
            pause.setOnAction(e -> {
                c.stopSim();
            });
            
             earth.setOnAction(e -> {
                c.setAdding();
                c.setNextBody(EpochJ2000.EARTH.getBody());
            });
    
            zoomUp.setOnAction(e -> {
            this.unit = c.zoomUp();
            });
    
            zoomDown.setOnAction(e -> {
                this.unit = c.zoomDown();
            });
    
            // this method closes the program
            primaryStage.setOnCloseRequest(e -> {
                this.c.exit();
                System.exit(0);
            });
    
            // Posto x e y come origine degli assi
            x = (primaryStage.getWidth() / 2) - 50;
            y = (primaryStage.getHeight() / 2) - 50;
    
            // Aggiunta bottoni al pannello
            root1.getChildren().add(play);
            root1.getChildren().add(pause);
            root1.getChildren().add(zoomLabel);
            root1.getChildren().add(zoomUp);
            root1.getChildren().add(zoomDown);
    
            c.startSim();
    
        }
    
        public void render(List<Body> b) {
    
        	//Fatto solo la prima volta
            //Prende lo Zoom inizale solo la prima volta..
            if (bool) {
                this.unit = c.getUnit();
                this.bool = false;
            }
    
            for (Body a : b) {
                if (planet_map.containsKey(a.getName())) {
                    planet_map.get(a.getName()).relocate((x + (a.getPosX() * unit)), (y - (a.getPosY() * unit)));
                    System.out.println(x + (a.getPosX() * unit) + "PosX schermo");
                    System.out.println(y - (a.getPosY() * unit) + "PosY schermo");
                    System.out.println(x + (a.getPosX()) + "PosX real");
                    System.out.println(y - (a.getPosY()) + "PosY real");
                }
    
                else {
                    planet_map.put(a.getName(),
                            new ImageView(new Image("/planet_images/" + a.getName().toLowerCase() + ".png")));
                    planet_map.get(a.getName()).setFitHeight(50);
                    planet_map.get(a.getName()).setFitWidth(50);
                    planet_map.get(a.getName()).setPreserveRatio(true);
                    planet_map.get(a.getName()).relocate(x, y);
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            root1.getChildren().add(planet_map.get(a.getName()));
                        }
                    });
    
                }
            }
    
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
        public Button getPlayButton() {
            return button_map.get("Play");
        }
    
        public Button getPauseButton() {
            return button_map.get("Pause");
        }
    
    }
    
    Il controller invece:
    
    package atlas.controller;
    
    
    /**
     * Implementation of ControllerInterface
     * 
     * @author andrea
     *
     */
    public class ControllerImpl implements Controller {
    
        private GameLoop gLoop;
        private static ControllerImpl ctrl = null;
        private View view;
        private Model model;
    
        private boolean adding = false; 
        private Body nextBody = null;
        double posy = 1;
        double unit = 1.4000000000000000E-9;
        boolean bool = true;
    
        private ControllerImpl() {
            gLoop = new GameLoop();
            gLoop.start();
        }
    
        public static ControllerImpl getIstanceOf() {
            return (ControllerImpl.ctrl == null ? new ControllerImpl() : ControllerImpl.ctrl);
        }
    
        @Override
        public void startSim() {
            gLoop.setRunning();
    
        }
    
        @Override
        public void stopSim() {
            gLoop.setStopped();
        }
    
        @Override
        public void exit() {
            gLoop.setExit();
        }
    
        public void setView(View v) {
            this.view = v;
            this.gLoop.setView(v);
        }
    
        @Override
        public void update(final EventType event, String path, Optional<Double> posX, Optional<Double> posY)
                throws IllegalArgumentException, IOException {
            switch (event) {
            case ADDING_BODY:
    
                this.nextBody.setPosX(posX.get() * unit);
                this.nextBody.setPosY(posY.get() * unit);
                this.model.addBody(nextBody);
                this.adding = false;
                this.nextBody = null;
                break;
    
            case SAVE:
                this.saveConfig(path);
                break;
    
            case LOAD:
                this.loadConfig(path);
                break;
    
            default:
                break;
            }
        }
    
        @Override
        public void setAdding() {
            this.adding = true;
        }
    
        @Override
        public void setNotAdding() {
            this.adding = false;
        }
    
        @Override
        public boolean isAdding() {
            return this.adding;
        }
    
        @Override
        public void setNextBody(Body body) {
            this.nextBody = body;
        }
    
        @Override
        public void reset() {
            this.nextBody = null;
            this.adding = false;
        }
    
        @Override
        public double getUnit() {
            return this.unit;
        }
    
        @Override
        public double zoomUp() {
            this.unit = unit * 1.05;
            return this.unit;
    
        }
    
        @Override
        public double zoomDown() {
            this.unit = unit * 0.95;
            return this.unit;
        }
    
        @Override
        public void saveConfig(String path) throws IOException, IllegalArgumentException {
            File f = new File(path);
            if (!this.checkFileExists(f)) {
                throw new IllegalArgumentException();
            }
    
            try (OutputStream bstream = new BufferedOutputStream(new FileOutputStream(f));
                    ObjectOutputStream ostream = new ObjectOutputStream(bstream);) {
                ostream.writeObject(this.model.getClock());
                ostream.writeObject(this.unit);
                // Speed
                ostream.writeObject(this.model.getBodiesToRender());
            }
        }
    
        @Override
        public void loadConfig(String path) throws IOException, IllegalArgumentException {
            File f = new File(path);
            if (!this.checkFileExists(f)) {
                throw new IllegalArgumentException();
            }
    
            try (InputStream bstream = new BufferedInputStream(new FileInputStream(f));
                    ObjectInputStream ostream = new ObjectInputStream(bstream);) {
                this.model.setClock((SimClock) ostream.readObject());
                this.unit = (Double) ostream.readObject();
                while (true) {
                    try {
                        this.model.addBody(((Body) ostream.readObject()));
                    } catch (Exception e) {
                        break;
                    }
                }
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException("Content of the file is not suitable.");
            }
        }
    
        /* True : exists, false otherwise */
        private boolean checkFileExists(File f) {
            return f.exists() && !f.isDirectory();
        }
    
    }
    
    Il problema come già detto è in update... quello che vorrei realizzare è un metodo che accetta un tipo di evento, rappresentato da una enumerazione, e tramite uno switch invocare i metodi del controller (che diventerebbero privati). Ora come ora, dalla view chiamo direttamente i metodi relativi ai pulsanti (Non lo trovo molto corretto, dato che dovrebbe essere il controller a capire l'evento e gestirlo). Il mio problema è come gestire il metodo update considerando che ogni evento invia input differenti al metodo update.

    Per gli eventi ho pensato ad una enumerazione:
    
    public enum EventType {
        SAVE, LOAD, ADDING_BODY, .....
    }
Devi accedere o registrarti per scrivere nel forum
2 risposte