9
votes

I am getting my feet wet with javafx. This is what I am doing.

FXML Views
DI Controllers
Weld-SE Managed Services and Models
Trying to confine UI to FXML
Trying keep the Controllers thin

Problem:

While trying to code the UI, most static UI is confined inside the fxml. But there are scenarios where I find my self adding, removing, showing, hiding elements etc.

I find myself doing this inside the controller as fx lets me configure controller method in the view which it will call on a particular action / event. All this code deals with Dynamic UI building / manipulating and belongs inside the view layer. But, it ends up in controller making the controllers fat.

javafx provides javascript integration. This is one possible way to abstract that view manupulation code away. But this would add not so perfect javascript into the mix.

How would I abstract the code away in java or fxml so that I don't break the Thin Controller Paradigm ?

EDIT

@assylias

Agreed, I have thought about this and this way that java class and fxml together become a reusable widget. But then, how do I wire this into FXML. FXML doesn't understand anything but a controller. Let say I wire this view class into fxml using fx:controller and not name it controller. So I have something like this.

enter image description here

This view class has nothing but view manipulation code. Then I would create another controller class. But then I would expect to somehow fill the form data into this controller. This should only happen when the user has submitted the form. So in a way, I need to tell javafx somehow that UI manipulation request / event is different from actual data manipulation request / event.

Your thoughts, sorry if it was verbose. Tried to articulate it in as few words as I could.

2
You could have FXML View, a Java View (a first layer of controller) that does the dynamic stuff and then a proper Java Controller, which extends the first one. (not sure that would work, just an idea). - assylias
You seem to try to apply the MVC pattern, but it's not needed for most scenarios. The controller in Java FX is not the controller of the MVC pattern as you already figured out (View Class in your diagram). So what problem do you want to solve? Can you provide a sample? - Puce
I was hoping to find out how to better organize my code and avoid code clutter. I thought others must have come across this problem way before me and must have found a workaround. - ShaggyInjun
Can you show us what kind of code clutter you have issues with? - Puce

2 Answers

1
votes

I think the easiest solution to this is to remember that the controller specified in FXML is a view controller. It's purpose is to contain code to modify and update the view, not to contain traditional MVC controller code or business logic.

For example, in a project I'm currently working on, I'm using JavaFX with Akka Actors. The application is written in scala. The JavaFX view controllers contain any code necessary to modify the view. One screen contains a login form. When the user clicks the login button, the view controller simply creates a message containing the username and password, and sends that message to the actor responsible for doing business logic. If that actor determines there is an error then it will send a message back to the view controller, and the view controller can decide what sort of updates need to be made on the screen.

I've found that using akka actors with JavaFX greatly simplifies coding the application for at least two reasons.

  1. Because using an actor system mandates sending messages between actors, there is a natural boundary between presentation code and business code. The messages that are passed back and forth form this natural boundary.
  2. Using actors completely replaces the complexity of working with threads/tasks. It completely eliminates the need to code javafx.concurrent.Task's for long running processes.
0
votes

How about putting your view manipulation code in Main Class ?

Main Class :

public class SampleJavaFXApp extends Application{

public static void main(String[] args) {
    launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
    FXMLLoader loader = new FXMLLoader(getClass().getResource(
            "SampleUI.fxml"));
    Parent root = (Parent) loader.load();
    Controller controller = loader.getController();
    viewManipulationLogic(controller);
    primaryStage.setScene(new Scene(root));
    primaryStage.show();    
}
       // view manipulation logic
private void viewManipulationLogic(Controller controller) { 
controller.getBlueButton().setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent arg0) {
            System.out.println(" I am just about button!");
        }
    }); 
}

Controller :

public class Controller implements Initializable {
    @FXML
    private Button blueButton;
    public Button getBlueButton() {
        return blueButton;
    }
@Override
    public void initialize(URL arg0, ResourceBundle arg1) {
         //real data manipulation
}
}

cons : You need getters for all Nodes u want to manipulate , in controller class.