'JavaFX MVC Connect Controller Button ActionEvent to Model and VIew correctly
So I'm developing a game with JavaFX MVC thinking (no FXML), the view is something like this here
and my code for the view is something like this (I still have to add the buttons in the bottom part of the view but I can already make a connection with the controller class):
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Button;
import javafx.scene.control.MenuBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Pair;
public class Main extends Application {
Button attackButton = new Button("Attacca");
Button marketButton = new Button("Market");
Button powerupButton = new Button("Power up");
Button createsoftwareButton = new Button("createsoftwareButton");
public Button getAttackButton() {
return attackButton;
}//da aggiungere nel sotto mappa
public Button getMarketButton(){
return marketButton;
}
public Button getPowerupButton(){
return powerupButton;
}
public Button getCreatesoftwareButton(){
return createsoftwareButton;
}
enum LivelloDiGioco {
Easy, Medium, Hard
}
public final Insets STANDARD_PADDING = new Insets(10);
PopUp popUp = new PopUp();
private Pair<Integer, Integer> getDimensioniMappa(LivelloDiGioco livello) {
int xMax, yMax;
switch (livello) {
case Easy:
xMax = 15;
yMax = 10;
break;
case Medium:
xMax = 20;
yMax = 15;
break;
default:
xMax = 30;
yMax = 20;
break;
}
return new Pair<>(xMax, yMax);
}
public static void main(String[] args) {
launch(args); // fa partire la funzione start di JavaFX
}
AddType aT = new AddType();
int click = 0;
@Override
public void start(Stage primaryStage) { // start della costruzione grafica
primaryStage.setTitle("Server Dominator");
primaryStage.setIconified(false); // se TRUE lo avvia ridotto a icona
primaryStage.setFullScreen(false); // apre in full screen
primaryStage.setX(0); // definisce la coordinata X dell'angolo in alto a sinistra della finestra
primaryStage.setY(0); // definisce la coordinata Y dell'angolo in alto a sinistra della finestra
//primaryStage.centerOnScreen();
Pair<Integer, Integer> dimensioneMappa = getDimensioniMappa(LivelloDiGioco.Hard);
MainDefinitivo mainView = new MainDefinitivo();
try {
mainView.avvioPartita(dimensioneMappa.getKey(), dimensioneMappa.getValue(), "Matteo", 10);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
VBox holder = new VBox();
BorderPane borderPane = new BorderPane();
Giocatore[] gioc = mainView.getGiocatori();
Nodo baseU = mainView.getTabellone().trovaBase(gioc[1]);
Base bU = new Base(baseU.getPossessore());
MappaDefinitiva mappa = new MappaDefinitiva(dimensioneMappa.getKey(), dimensioneMappa.getValue(), gioc);
mappa.assegnamento(gioc.length-1, gioc);
Nodo[][] nodiView = mappa.getMap();
MapData mapData = new MapData(nodiView);
int ray = mapData.getRay();
// ------ Game table ----------//
ScrollPane centerPane = new ScrollPane();
PlayTable pt = new PlayTable(dimensioneMappa);
centerPane = pt.getPlayTable(dimensioneMappa, mapData, bU, ray);
Canvas basicCanvas = pt.getBasicCanvas();
//GraphicsContext basicGC = pt.getBasicCanvas();
BasicMap basicMap = new BasicMap(mapData, basicCanvas.getGraphicsContext2D());
basicMap.selected = true;
ArrayList<Map> mapOrder = new ArrayList<>();
mapOrder.add(basicMap);
double[] h = new double[1000];
double[] w = new double[1000];
h[click] = centerPane.getHeight(); w[click] = centerPane.getWidth();
StatsNodePane sPane = new StatsNodePane(bU);
//offset scroll risolto
centerPane.setOnMouseClicked(event -> {
double xMouse=event.getX();
double yMouse=event.getY();
double xBase=pt.getBasicCanvas().getWidth()-(pt.getScrollPane().getViewportBounds().getMaxX()-pt.getScrollPane().getViewportBounds().getMinX());
double yBase=pt.getBasicCanvas().getHeight()-(pt.getScrollPane().getViewportBounds().getMaxY()-pt.getScrollPane().getViewportBounds().getMinY());
double xOffset=(pt.getScrollPane().getHvalue()/pt.getScrollPane().getHmax())*xBase;
double yOffset=(pt.getScrollPane().getVvalue()/pt.getScrollPane().getVmax())*yBase;
System.out.println(
"----inizio---\n"
+pt.getScrollPane().getViewportBounds().toString()+"\n"
+"\nxScorriBarra,yScorriBarra\t"+pt.getScrollPane().getHvalue()+","+pt.getScrollPane().getVvalue()
+"\nxMaouse,yMaouse\t"+xMouse+","+yMouse
+"\nxBase,yBase\t"+xBase+","+yBase
+"\nxOffset,yOffset\t"+xOffset+","+yOffset+"\n"
+"----fine---");
Hexagon est = mapData.pixelToHex(new Point(xMouse+xOffset,yMouse+yOffset));
System.out.println("vvVAlue"+pt.getScrollPane().vvalueProperty().doubleValue()+"\nvvMax"+pt.getScrollPane().vmaxProperty()
+"\n pane size: "+pt.getScrollPane().getViewportBounds());
HexData data = mapData.getHexData(est);
// ----------'offset on scroll --------------//
if (data != null) {
click++;
//h[click] = centerPane.getHeight(); w[click] = centerPane.getWidth();
//System.out.println("Dal click " + (click-1) + " al " + click + " -> diffHeight(): " + (h[click] - h[click-1]));
//System.out.println("Dal click " + (click-1) + " al " + click + " -> diffWidth(): " + (w[click] - w[click-1]));
//System.out.println("centerPane.getWidth(): " + centerPane.getWidth() + "click: " + click);
}
// -----------------------------------------------------------------------//
if (data != null) { // controllo se il click avviene fuori dagli esagoni
Nodo nodo = data.nodo;
// ---- values in Stats Node ---------//
sPane.titleL.setText("Stats Node: " + est.x + " , " + est.y);
sPane.owner.setText("Owner: " + nodo.getPossessore().getNome());
sPane.distance.setText("Base distance: " + nodo.getDist_base());
sPane.energy.setText("Energy: " + nodo.getE_disponibile());
sPane.fwLvl.setText("Firewall Level: " + String.valueOf(nodo.getLvl_firewall()));
sPane.ramLvl.setText("Ram Level: " + String.valueOf(nodo.getLvl_ram()));
sPane.cpuLvl.setText("CPU Level: " + String.valueOf(nodo.getLvl_cpu()));
basicMap.drawMap(est);
}
});
// ----------- Menù ----------- //
SDMenuBar sdM = new SDMenuBar();
MenuBar sdMenuBar = new MenuBar();
sdMenuBar = sdM.getMenuBar();
// -------- undermap ------------//
HBox sottoMappa = new HBox();
Pane statsNodePane = new Pane();
statsNodePane = sPane.getSnPane(bU);
BattlePane bPane = new BattlePane(bU);
Pane battlePane = new Pane();
battlePane = bPane.getBattlePain(bU);
ActionPane aPane = new ActionPane(bU);
Pane actionPane = new Pane();
actionPane = aPane.getActionPane(bU);
// ------------------------------------------ //
HBox.setHgrow(statsNodePane, Priority.ALWAYS);
HBox.setHgrow(battlePane, Priority.ALWAYS);
HBox.setHgrow(actionPane, Priority.ALWAYS);
sottoMappa.getChildren().addAll(statsNodePane, battlePane, actionPane);
// ------------------------------------------ //
// Pane yourBase right side of map
BaseStatsPane rPane = new BaseStatsPane(bU);
Pane yourBasePane = new Pane();
yourBasePane = rPane.getBsPane(bU);
// Setting BorderPane
borderPane.setTop(sdMenuBar);
borderPane.setCenter(centerPane);
BorderPane.setMargin(centerPane, new Insets(10));
borderPane.setBottom(sottoMappa);
BorderPane.setMargin(sottoMappa, new Insets(0, 10, 10, 10));
borderPane.setRight(yourBasePane);
BorderPane.setMargin(yourBasePane, new Insets(10, 10, 10, 0));
// Adding MenuBar and BorderPane to a VBox Holder
holder.getChildren().addAll(sdMenuBar, borderPane);
Scene scena = new Scene(holder);
scena.getStylesheets().add("application.css");
primaryStage.setScene(scena);
primaryStage.show();
new AnimationTimer() {
@Override
public void handle(long now) {
// pulisco la mappa
basicCanvas.getGraphicsContext2D().clearRect(0, 0, basicCanvas.getWidth(), basicCanvas.getHeight());
// disegno la mappa
basicMap.drawMap();
}
}.start();
}
}
while my model class has all the methods I need
import java.util.Collections;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.controller.PartitaUIController;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.model.giocatore.Bot;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.model.giocatore.Classifica;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.model.giocatore.Giocatore;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.model.giocatore.Mercato;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.model.giocatore.Sistema;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.model.giocatore.Utente;
import javafx.scene.control.Button;
public class MainDefinitivo extends Thread{
private MappaDefinitiva tabellone;
private int n_basi;
private Giocatore[] giocatori;
private Mercato mercato;
private int t_unitario, t_timer;
Thread threadBot[];
private Classifica classifica;
private PartitaUIController partitaUIController;
private Battaglia[] fight;
private int maxbattle=7;
private int count;
//private int tempoAggiornamento;
//private boolean giocoAttivo=false;
public static void main(String[] args) {
// TODO Auto-generated method stub
//prova 1:avvio partita
/* MainDefinitivo main = new MainDefinitivo();
try {
main.avvioPartita(30, 20, "Matteo");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
//selezione utente
//selezione lingua
public void avvioPartita(int x_max, int y_max, String nomeUtente, int valuta) throws InterruptedException {
//giocoAttivo=true;
t_unitario=10;
this.creazioneGiocatori(nomeUtente, x_max, valuta);
tabellone = new MappaDefinitiva(x_max, y_max, giocatori);
mercato=new Mercato();
classifica= new Classifica(giocatori);
fight= new Battaglia[maxbattle];
this.avvioBot(); //Matteo P. L'ho commentato perchè mi blocca dentro al while di avvioBot
/*/gioco finito
giocoAttivo=false;
this.stopBot();*/
}
public void creazioneGiocatori(String utente, int x_max, int valuta) {
Collections.shuffle(Colore.colori);
switch(x_max) {
case 15:
n_basi=3;
giocatori= new Giocatore[n_basi+1];
giocatori[0]= new Sistema();
giocatori[0].colore = Colore.GRIGIO;
giocatori[1]= new Utente(utente, valuta);
giocatori[2]= new Bot("bob");
giocatori[3]= new Bot("sandra");
break;
case 20:
n_basi=5;
giocatori= new Giocatore[n_basi+1];
giocatori[0]= new Sistema();
giocatori[0].colore = Colore.GRIGIO;
giocatori[1]= new Utente(utente, valuta);
giocatori[2]= new Bot("bob");
giocatori[3]= new Bot("sandra");
giocatori[4]= new Bot("roger");
giocatori[5]= new Bot("max");
break;
case 30:
n_basi=10;
giocatori= new Giocatore[n_basi+1];
giocatori[0]= new Sistema();
giocatori[0].colore = Colore.GRIGIO;
giocatori[1]= new Utente(utente, valuta);
giocatori[2]= new Bot("bob");
giocatori[3]= new Bot("sandra");
giocatori[4]= new Bot("roger");
giocatori[5]= new Bot("max");
giocatori[6]= new Bot("jupiter");
giocatori[7]= new Bot("alex");
giocatori[8]= new Bot("lonfo");
giocatori[9]= new Bot("mara");
giocatori[10]=new Bot("alice");
break;
}
for (int i = 1; i < giocatori.length; i++) {
giocatori[i].colore = Colore.colori.get(i-1);
}
}
@SuppressWarnings("static-access")
public void avvioBot() throws InterruptedException {
int i;
for(i=2; i<=n_basi; i++) {
giocatori[i].setMap(tabellone);
giocatori[i].start();
}
}
public void stopBot() throws InterruptedException {
int i;
for(i=2; i<=n_basi; i++) {
giocatori[i].interrupt();
}
}
//----------------metodi per potenziamento---------------//
public boolean powerupCheck(int x, int y){
/** metodo chiamato dopo che l'utente ha selezionato un nodo di
* sua proprieta, abilita il pulsante per eventuali potenziamenti risorse.
*/
boolean checkp= false;
if(tabellone.getNodo(x, y).getPossessore()==giocatori[1]) {
checkp=true;
}
return checkp;
}
public void powerup(int x, int y, String risorsa) {
/** metodo lanciato dopo aver selezionato la risorsa da potenziare
* dall'interfaccia grafica.
*/
if(this.powerupCheck(x, y)) {
tabellone.getNodo(x, y).potenzia_risorsa(risorsa);
}
}
//------------metodi per creazione software----------//
public boolean softcheck(int x, int y) {
/** il metodo viene lanciato quando l'utente clicca su un nodo
* di sua proprieta e abilita il pulsante per la creazione software.
*/
boolean checks=false;
if(tabellone.getNodo(x, y).getPossessore()==giocatori[1]) {
checks=true;
}
return checks;
}
public void creazioneSoftware(String nome, int quantita, int x, int y) {
/** metodo usato dopo la selezione del software da parte dell'utente
*
*/
if(this.softcheck(x, y)) {
tabellone.getNodo(x, y).crea_software(nome, quantita);
}
}
//------------- metodi per mercato------------//
public void acquistoMercato(int quantita, String oggetto) {
//if(quantita==-1)
//mercato.compraRisorse(utente, tabellone.trovaBase(utente), oggetto);
//else
//mercato.compraSoftware(utente, tabellone.trovaBase(utente), quantita, oggetto);
}
//---------------metodi per battaglia-------------//
public boolean nodecheck(Giocatore attaccante, int x, int y) {
/** metodo per il controllo se un nodo e' attaccabile,
* controlla anche se lo spazio disponibile per gli attacchi simultanei
* non e' vuoto.
* NB: un utente puo' eseguire 6 attacchi simultaneamente.
* metodo eseguito quando un utente clicca su un nodo
*/
boolean checkf=false;
if(maxbattle>0) {
if(tabellone.attaccabile(x,y, attaccante)) {
checkf=true;
}
}
return checkf;
}
public void battlecheck(Giocatore attaccante, int x, int y,int quantitaV, int quantitaR) {
/** il seguente metodo, gestisce le operazioni preliminari alla battaglia
* dati due interi, le coordinate del nodo bersaglio, e il Giocatore attaccante.
* le quantita di software dovranno essere inizializati correttamente tramite un metodo del controllore
* che restituisce il numero di virus e rootcrash che l'utente seleziona
* in fase di attacco dall'interfaccia grafica.
* il metodo viene lanciato quando il giocatore clicca sul pulsante attacca
*/
if(this.nodecheck(attaccante, x, y)){
t_timer=t_unitario+(t_unitario*tabellone.dist_minima(x,y, attaccante).getDist_base() );
fight[maxbattle]=new Battaglia(tabellone.trovaBase(attaccante), tabellone.getNodo(x,y), t_timer);
fight[maxbattle].setPartenza(tabellone.dist_minima(x, y, attaccante));
fight[maxbattle].selezione(quantitaV, quantitaR);
count=maxbattle;
maxbattle--;
}
}
public void avvioBattaglia(PartitaUIController partitaUIController, Giocatore attaccante, int x, int y) {
/** metodo che lancia il thread relativo alla singola battaglia,
* successivo ai controlli di prossimit� e numeri di attacchi contemporanei,
* questo metodo viene lanciato quando l'utente clicca su conferma, per confermare i
* software da inviare in battaglia.
*/
fight[count].start();
/*le due istruzioni seguenti sono da lanciare una volta terminato l'esecuzione
* del thread di battaglia
*/
maxbattle++;
classifica.aggiornaClassifica();
System.out.println( fight[count].getReport() );
}
//-------------metodi di fine partita------------//
public Classifica gameover() {
/** metodo usato alla fine della partita per restituire la classifica finale della partita
* e stampare a video il nome del giocatore vincitore
*/
Giocatore vincitore;
vincitore= classifica.getVincitore();
System.out.println("il vincitore e': " + vincitore.getNome());
return classifica;
}
/**getter and setter */
public int getX_max() {
return tabellone.getX_max();
}
public int getY_max() {
return tabellone.getY_max();
}
public MappaDefinitiva getTabellone() {
return tabellone;
}
public Giocatore[] getGiocatori() {
return giocatori;
}
public boolean nodecheck(Button attackButton, Giocatore attaccante, int x, int y) {
/** metodo per il controllo se un nodo e' attaccabile,
* controlla anche se lo spazio disponibile per gli attacchi simultanei
* non e' vuoto.
* NB: un utente puo' eseguire 6 attacchi simultaneamente.
* metodo eseguito quando un utente clicca su un nodo
*/
boolean checkf=false;
if(maxbattle>0) {
if(tabellone.attaccabile(x,y, attaccante)) {
checkf=true;
}
}
return checkf;
}
}
While that's ok, they load correctly alongside the subclasses. My issues are in the controller class between them that connects the buttons to the desired methods. when I set an actionEvent for a button it connects correctly to the view class, but when I try to connect the same actionEvent to the model method it asks me to create an exact method that I already coded in the model class! Except with the button that I stated in the view as a parameter for each method in the model!
Here's the unfinished controller class:
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.model.giocatore.Giocatore;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.view.Login;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.view.Main;
import it.unipv.ingInf.ingSW.deltaTech4Java.serverDominator.model.MainDefinitivo;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class PartitaUIController {
//model
MainDefinitivo mainDefinitivo;
public PartitaUIController(Main mainView){
setView(mainView);
}
private void setView(Main mainView) {
//get model
mainDefinitivo = new MainDefinitivo(); //pass parameters?
//link - methods for buttons
//attack button
mainView.getAttackButton().setOnAction(actionEvent -> {
mainDefinitivo.nodecheck(mainView.getAttackButton());
mainDefinitivo.battlecheck(mainView.getAttackButton());
mainDefinitivo.avvioBattaglia();
actionEvent.consume();
});
//button for switching scene, marketplace scene
Stage primaryStage;
mainView.getMarketButton().setOnAction(actionEvent -> primaryStage.setScene(marketView));
//stage.setScene()
);
// power up button
mainView.getPowerupButton().setOnAction(actionEvent -> {
mainDefinitivo.powerupCheck(mainView.getPowerupButton());
mainDefinitivo.powerup(mainView.getPowerupButton());
});
//button to create software
mainView.getCreatesoftwareButton().setOnAction(actionEvent -> {
});
}
}
Then the error is in the mainView.getNameButton() part, but model and view shouldn't communicate directly like that. So how should I fix this in a correct way?
Thank you and kind regards.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
