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, .....
}