I'm new to JavaFX and I was wondering what are the best practices in this language to develop a MVC database application, I think my question will be pretty simple if you are an senior developer.
Let us consider a simple example of a basic application developed in JavaFX : a ToDoList linked with a SQL Database.
- The database is just one table Task with an id and a taskDescr VARCHAR field.
- The purpose is pretty easy : we just want to display the task in a TableView or ListView and be able to add some tasks.
That's what our application looks like :
ToDoList GUI
I decided to split my code into four parts, DAO for the classes who represents datas in the table (Task.java), the DAO class who access the database (its behavior does not matter here). The model who represents the Model part of our TodoList (containing a list of task and performing operations on it, calling the DAO, etc..). The FXML Views and the Controller :
Project structure
Next, you can find the code of the different classes that interest us (We supposed that the DAO is OK (setting id automatically) an we do not handle error cases to simplify code :
Task.java
public class Task {
private int id;
private SimpleStringProperty task;
public Task(int i, String s){
this.id = i;
this.task = new SimpleStringProperty(s);
}
public void setId(int i){
this.id = i;
}
public int getId() {
return id;
}
public String getTask() {
return task.get();
}
public void setTask(String task) {
this.task.set(task);
}
@Override
public boolean equals(Object o){
if(this.id == ((Task)o).id)
return true;
return false;
}
}
ToDoListModel.java
public class ToDoListModel {
private List<Task> taskList;
private DAO dao;
public ToDoListModel(){
this.taskList = new ArrayList<Task>();
this.dao = new DAO();
}
public void loadDatabase(){
this.taskList = this.dao.getAllTasks();
}
public void addTask(Task t){
// Operations throwing Exceptions such as : Does the task t is already in the list, etc...
this.taskList.add(t);
this.dao.createTask(t);
}
public void deleteTask(Task t){
this.taskList.remove(t);
this.dao.deleteTask(t);
}
public List<Task> getTaskList() {
return taskList;
}
}
Controller.java
public class Controller {
private final ToDoListModel model;
@FXML
private TableView<Task> taskTable;
@FXML
private TableColumn<Task, String> taskColumn;
@FXML
private TextField taskTextField;
public Controller(ToDoListModel m){
this.model = m;
}
@FXML
protected void initialize() {
this.model.loadDatabase();
// Setting up data table
taskColumn.setCellValueFactory(new PropertyValueFactory<Task, String>("task"));
ObservableList<Task> taskObservableList = FXCollections.observableList(this.model.getTaskList());
taskTable.setItems(taskObservableList);
}
@FXML
public void handleAddButton(ActionEvent e) {
Task t = new Task(-1, this.taskTextField.getText());
// What operations to do here ?
this.model.addTask(t);
this.taskTable.getItems().add(t);
this.taskTable.refresh();
}
}
Main.java
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
ToDoListModel model = new ToDoListModel();
primaryStage.setTitle("My Todo");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("views/View.fxml"));
loader.setController(new Controller(model));
Parent root = loader.load();
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Finally, my question is : Is my approach good ? I mean the fact that I've created a ToDoListModel with a list of task, the fact that I update my list of Objects Task at the same task I update my database with the DAO (a create in the DAO will be performed after an add in the list) and the most important : what operations should I do in the handleAddButton of my Controller ? Here I used first the add method in my TodoListModel but it's not enough because my observable list is wrongly updated (The added task appears but we can not select it with the mouse). Then, when I add it also in the TableView items, the Task appears twice and has been added twice in the list.
As a result I've understood that the ObservableList was linked to the List I have in my ToDoListModel but what am I supposed to do if I want to do operations on that list only in my model but getting the ObservableList updated correctly ? (Selectable item etc...)
Duplication example
Thank you in advance for your help and your patience, Sincerely, Paul