JavaFx : How to tell my main class to do something from my controller?

822 views Asked by At

i'm trying to build my first program and i'm having trouble communicating between the javaFX controllers and my main application class.

The program is a countdown: you enter a number of hour and minute and it'll launch a pop-up window when the countdown is over.

Here's my main controller's buttonClicked function :

@FXML
private TextField heure;
@FXML
private TextField minute;
@FXML
private Button launchButton;
private String hour,minutes;

public void launchButtonClicked(){
    hour = heure.getText();
    minutes = minute.getText();

    try {
          int h = Integer.parseInt(hour);
          int m = Integer.parseInt(minutes);

          System.out.println("MenuController");


    } catch (NumberFormatException e) {
          //Will Throw exception!
          //do something! anything to handle the exception.
    }

}

and here's the main class :

public class Main extends Application {
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);


@Override
public void start(Stage primaryStage) {
    try {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Menu.fxml"));
        Parent root = loader.load();
        Scene scene = new Scene(root,800,500);
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {
    launch(args);
}

public void rappel(int h,int m){
    System.out.println("Rappel" + h + m);
    int minute = (h*60 + m) - 5;        
    final Runnable rappel = new Runnable(){
        public void run(){
            AlertBox box = new AlertBox();
            box.display("Reminder","Rappel : 5 min");
        }
    };

    final ScheduledFuture<?> rappelHandle = scheduler.schedule(rappel, minute, TimeUnit.MINUTES);
    scheduler.schedule(new Runnable() {
        public void run() { rappelHandle.cancel(true); }
    }, 60 * 60, TimeUnit.SECONDS);
}
}

What i want to do is, when the launchButton is clicked, tell my main function to use the rappel(int h,int m) function. It'll launch an alertBox which displays a String i want.

I feel like i'm not using the controller right because i didnt find a way from my controller to "give orders" to my main app class.

Do you have any idea on how this could work ? Should i use another way to pop-up an alertbox than the scheduledexecutorservice ?

Ps: I didn't bother writing the test and exceptions handling yet. I promise i'll do when i manage to make it work !

1

There are 1 answers

0
Fedor Losev On

One simple way to communicate between componets is to add a listener property to controller class and add a listener from main.

Note, there are cleaner ways to wire JavFX things together, depending on program needs, but I'll not go into this here as it depends and there are enough tutorials about design patterns. Here is a way just to answer the programming question and is enough to run your program:

In controller

class YourControllerClass{
...
    Runnable launchListener;

    public void setLaunchListener(Runnable launchListener){
        this.launchListener = launchListener;
    }
...

in main:

...
controller = (YourControllerClass) loader
                        .getController();
controller.setLaunchListener(() -> {
                    rappel(1,2)
                });

I used Runnable here as it is built-in. If you need to pass parameters from the controller, define an interface and use it instead of Runnable:

In controller

class YourControllerClass{
...
  public static interface ILaunchListener{
    public void onLaunch(int h, int m);
  }

  ILaunchListener launchListener;

  public void setLaunchListener(ILaunchListener launchListener){
      this.launchListener = launchListener;
  }

  public void launchButtonClicked(){
    if(launchListener!=null){
        hour = heure.getText();
        minutes = minute.getText();

        try {
              int h = Integer.parseInt(hour);
              int m = Integer.parseInt(minutes);

              launchListener.onLaunch(h, m);


        } catch (NumberFormatException e) {
              //Will Throw exception!
              //do something! anything to handle the exception.
        }
    }
  }

...

in main:

...
controller = (YourControllerClass) loader
                        .getController();
controller.setLaunchListener((h, m) -> {
                    rappel(h,m)
                });