W samym MVC (czyli Model-View-Controller) chodzi o to, że kontroler zarządza modelem i widokiem.
Model to jest jakaś funkcjonalność, którą ma spełniać aplikacja np. dodawanie dwóch liczb. Operacja ta jest niezależna od widoku. Widok ma dostarczać elementy, które mają pojawić się na ekranie. W przykładzie dodawania będą to dwa pola tekstowe na wprowadzenie wartości oraz jakaś etykieta na wynik. Zadaniem kontrolera jest pośrednictwo między użytkownikiem, funkcjami aplikacji (czyli modelem) oraz tym co ma być wyświetlane (czyli widokiem).
Zrobiłem kiedyś przykład MVC w konsoli, może też Ci to coś wyjaśni:
https://github.com/mbabanes/java-examples/tree/master/src/main/java/console
W przypadku JavyFx widoki mają postać plików FXML (mogą być też zapisane w Javie). Kontroler, który ma przypisany jakiś FXML (właściwie w JavieFX jest troszkę na odwrót bo to w FXML'u przypisujemy kontroler do widoku, ale z logicznego punktu widzenia to widok przypisywany jest do kontrolera nie odwrotnie - to kontroler ma zarządzać widokiem, nie widok kontrolerem). Przykładowy FXML aplikacji do dodawania dwóch liczb:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="mvc.controller.Controller">
<children>
<TextField fx:id="number1" layoutX="147.0" layoutY="53.0" promptText="Liczba 1"/>
<TextField fx:id="number2" layoutX="147.0" layoutY="105.0" promptText="Liczba 2"/>
<Label fx:id="resultLabel" layoutX="223.0" layoutY="250.0">
<font>
<Font size="24.0"/>
</font>
</Label>
<Button layoutX="208.0" layoutY="169.0" mnemonicParsing="false" onAction="#buttonOnAction" text="Dodaj"/>
</children>
</Pane>
W kontrolerze można przypisać jakieś konkretne kontrolki do zmiennych Javowych. Tutaj będzie potrzebny dostęp do pól tekstowych aby pobrać z nich wprowadzone przez użytkownika dane oraz do etykiety (Label) aby wyświetlić wynik. Dodatkowo w fxmlu można przypisać od razu metody akcji. W tym przypadku taka metoda została przypisana do kliknięcia przycisku. W kontrolerze musi znaleźć się jej sygnatura bo inaczej JavaFx nie zadziała.
Kwestia modelu w tym przypadku jest bardzo prosta. Model czyli logika aplikacji. Logiką jest tutaj dodanie dwóch liczb. Przykładowy model:
public class Model
{
public int add(int a, int b)
{
return a+b;
}
}
Kod kontrolera:
public class Controller
{
@FXML
private TextField number1;
@FXML
private TextField number2;
@FXML
private Label resultLabel;
private Model model = new Model();
@FXML
void buttonOnAction(ActionEvent event)
{
int a = Integer.valueOf( number1.getText() ); //pobiranie wartości pierwszej
int b = Integer.valueOf( number2.getText() ); //pobieranie wartości drugiej
int result = model.add(a, b); //dodanie wartośći, za co odpowiada model
resultLabel.setText(String.valueOf(result)); //przeslanie wyniku do widoku.
}
}
Kontroler nic nie rysuje, ani nie oblicza on tylko pobiera dane wprowadzone przez uzytkownika i przekazuje je do modelu, po czym przesyła wynik do widoku.
Zauważ teraz jedną rzecz. Sam widok jak i logika aplikacji to całkowicie niezależne byty. Można wziąć klasę modelu i bez żadnych przeszkód użyć jej np. w innym projekcie, czy przetestować jednostkowo:
Model model = new Model();
int a = 15;
int b = 12;
int result = model.add(a, b);
System.out.println( result );
A jeśli chcesz np. zmienić coś w widoku np. układ kontrolek czy kolorki czy coś, to robisz to tylko w FXML bez wchodzenia do klasy kontrolera i dokonywaniu modyfikacji (no chyba, że dokładasz jakąś kontrolkę z akcją - kolejny przycisk czy coś, wtedy trzeba dodać jakąś obsługę w kontrolerze).
W MVC chodzi o to, że oddzielasz to co ma zrobić aplikacja od tego co i jak ma wyświetlić - nie mieszane są te dwa elementy bo można przecież by było napisać to np. tak:
public class Controller
{
@FXML
private TextField number1;
@FXML
private TextField number2;
@FXML
private Label resultLabel;
@FXML
void buttonOnAction(ActionEvent event)
{
int a = Integer.valueOf(number1.getText());
int b = Integer.valueOf(number2.getText());
int result = a + b;
resultLabel.setText(String.valueOf(result));
}
}
Tzn bez modelu, ale brudzisz wtedy sobie klasę kontrolera bo zaczyna ona nie tylko obsługiwać zachowanie użytkownika ale także skupia w sobie to co aplikacja ma robić.
Do JavaFx według mnie całkiem niezły jest ten wideo tutorial:
https://www.youtube.com/playlist?list=PLpzwMkmxJDUwQuQR7Rezut5UE_8UGDxkU