0

I have a progress bar that I am trying to update within javaFX in a controller. I am updating the progress bar based on a function called Generate(), if it is called it should update the progress bar within the main controller. However, the code I have doesn't update it, rather it updates a new instance of the progress bar.

The Generate method in my DrawerContentController is :

    try {
    AnchorPane ap = fxmlLoader.load();
    for(Node node: ap.getChildren()){
        if(node.getId().equals("progressBar")){
            progressBar = (ProgressBar) node;
            progressBar.setProgress(50);
        }
    }

} catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

In my main controller I have the progressBar set up via fxml using scene builder, i'm trying to update the progressBar from DrawerContentController, which is essentially a sidebar menu that consists of 3 buttons, one of which is generate that calls the Generate() method. I know I should probably be using threads, I am a beginner to JavaFX and still learning on how to use it fully.

I've also tried :

FXMLLoader fxmlLoader = new FXMLLoader((getClass().getResource("layout.fxml")));

and then declaring the controller and instantiating it by

FXMLDocumentController fxmldc = fxmlLoader.getController();

and then assessing the property, however I get a npe this way.

My FXMLDocumentController

@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    //Load Splash screen
    if (!MainClass.isSplashLoaded)
        loadSplashScreen();

    //load drawer content
    try {
        VBox box = FXMLLoader.load(getClass().getResource("drawerContent.fxml"));
        drawer.setSidePane(box);

        HamburgerBasicCloseTransition transition = new HamburgerBasicCloseTransition(hamburger);
        transition.setRate(-1);
        hamburger.addEventHandler(MouseEvent.MOUSE_CLICKED, (e) -> {
            transition.setRate(transition.getRate() * -1);
            transition.play();

            if (drawer.isShown()) {
                drawer.close();
                mainText.setVisible(true);
            } else {
                drawer.open();
                mainText.setVisible(false);
            }

        });
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}
Taranjit Kang
  • 2,510
  • 3
  • 20
  • 40
  • The anchor pane, and consequently the progress bar inside it, are never displayed. So changing the progress property of the progress bar will have no visible effect. – James_D Mar 15 '17 at 18:05
  • FXMLLoader fxmlLoader = new FXMLLoader((getClass().getResource("layout.fxml"))); fxmldc1 = fxmlLoader.getController(); fxmldc1.setProgress(50); – Taranjit Kang Mar 15 '17 at 18:05
  • In the second code block, you never actually load the FXML, so the controller will be null. – James_D Mar 15 '17 at 18:06
  • ive tried FXMLLoader fxmlLoader = new FXMLLoader(); fxmlLoader.load(getClass().getResource("layout.fxml"); fxmldc1 = fxmlLoader.getController(); fxmldc1.setProgress(50); but this will create a new instance, and not update the existing instance from what i udnerstand. – Taranjit Kang Mar 15 '17 at 18:10
  • In that case, you are calling the *static* `FXMLLoader.load(URL)` method. So the controller still won't be initialized in the `fxmlLoader` instance. You would need `FXMLLoader fxmlLoader = new FXMLLoader(URL);` then `AnchorPane ap = fxmlLoader.load();` and `fxmldc1 = fxmlLoader.getController()`. But, as you say, this would still have the same problem in the initial code block you attempt: *the controller is attached to an anchor pane that is not displayed*. – James_D Mar 15 '17 at 18:15
  • Bottom line is you need to get the controller when you actually load *and display* the FXML file (or do something else entirely, like expose an observable progress property in the `DrawerContentController`). No idea where and when you do that as you didn't post that code. You should create a [MCVE]. – James_D Mar 15 '17 at 18:18
  • Ty for help thus far, i've added the the code where I load and display the drawerContent fxml. It is essentially a nav bar that pops out. – Taranjit Kang Mar 15 '17 at 18:30

1 Answers1

1

Just create an observable property in DrawerContentController for the progress:

public class DrawerContentController implements Initializable {

    private final DoubleProperty progress = new SimpleDoubleProperty();

    public DoubleProperty progressProperty() {
        return progress ;
    }

    public final double getProgress() {
        return progressProperty().get();
    }

    public final void setProgress(double progress) {
        progressProperty().set(progress);
    }

    // existing code...

}

Now you can bind your progress bar's progress property to the controller's progress property:

@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    //Load Splash screen
    if (!MainClass.isSplashLoaded)
        loadSplashScreen();

    //load drawer content
    try {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("drawerContent.fxml"));
        VBox box = loader.load();

        DrawerContentController drawerContentController = loader.getController();
        progressBar.progressProperty().bind(drawerContentController.progressProperty());

        drawer.setSidePane(box);

        // ... existing code
    }

    // ...
}

Now in your DrawerContentController class, if you do this.setProgress(...) (updating the new progress property you defined), it will automatically update the progress bar.

James_D
  • 201,275
  • 16
  • 291
  • 322