Search code examples
javajavafxgluongluon-mobile

How can I access the fields of a controller class, from a regular class? - JavaFX Gluon


I'm using JavaFX to create Android/Iphone applications by using the Gluon framework.

I know that this type of "how can I get the controller class" question. But this is different.

I know how to get the controller class, but that's is not what I asking for. I asking how I can access the fields from a controller class, without creating any new objects.

Assuming that we have a JavaFX controller class like this:

public class PrimaryPresenter {

    @FXML
    private View primary;

    @FXML
    public LineChart<String, Number> lineChart; // Every time we update the socket, we update the chart too

    public void initialize() {

        primary.setShowTransitionFactory(BounceInRightTransition::new);
        primary.showingProperty().addListener((obs, oldValue, newValue) -> {
            if (newValue) {
                AppBar appBar = MobileApplication.getInstance().getAppBar();
                appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> 
                        MobileApplication.getInstance().getDrawer().open()));
                appBar.setTitleText("Plot");

            }
        });   

        /*
         * Initial stuffs for the lineChart
         */
        lineChart.setTitle("Adaptive MPC");
    }


}

And I want to access the lineChart object from another class without creating a new PrimaryPresenter controller class. The FXML file is created by Scene Builder.

The reason why I'm asking this question, is because I have another class that loops via a thread and that thread will update the lineChart object in real time.


Solution

  • Here is my answer. In every Gluon project, there is a class named GluonApplication and it looks like this:

    package com.gluonapplication;
    
    import com.gluonapplication.thread.SocketConnection;
    import com.gluonapplication.views.PrimaryView;
    import com.gluonapplication.views.SecondaryView;
    import com.gluonhq.charm.glisten.application.MobileApplication;
    import com.gluonhq.charm.glisten.visual.Swatch;
    import javafx.scene.Scene;
    import javafx.scene.image.Image;
    import javafx.stage.Stage;
    
    public class GluonApplication extends MobileApplication {
    
        public static final String PRIMARY_VIEW = HOME_VIEW;
        public static final String SECONDARY_VIEW = "Secondary View";
    
        @Override
        public void init() {
            addViewFactory(PRIMARY_VIEW, () -> new PrimaryView().getView());
            addViewFactory(SECONDARY_VIEW, () -> new SecondaryView().getView());
            DrawerManager.buildDrawer(this);
        }
    
        @Override
        public void postInit(Scene scene) {
            Swatch.GREEN.assignTo(scene);
    
            scene.getStylesheets().add(GluonApplication.class.getResource("style.css").toExternalForm());
            ((Stage) scene.getWindow()).getIcons().add(new Image(GluonApplication.class.getResourceAsStream("/icon2.png")));
    
        }
    }
    

    To have access to all the fields form the controller classes. Just do this:

    public class GluonApplication extends MobileApplication {
    
        public static final String PRIMARY_VIEW = HOME_VIEW;
        public static final String SECONDARY_VIEW = "Secondary View";
        private SocketConnection socketConnection;
        private View primaryView; // Add
        private View secondaryView; // Add
    
        @Override
        public void init() {
            primaryView = new PrimaryView().getView();
            secondaryView = new SecondaryView().getView();
            addViewFactory(PRIMARY_VIEW, () -> primaryView);
            addViewFactory(SECONDARY_VIEW, () -> secondaryView);
            DrawerManager.buildDrawer(this);
    
            /*
             * This will start the socket connection
             */
            socketConnection = new SocketConnection(primaryView, secondaryView);
            socketConnection.start();
        }
    
        @Override
        public void postInit(Scene scene) {
            Swatch.GREEN.assignTo(scene);
    
            scene.getStylesheets().add(GluonApplication.class.getResource("style.css").toExternalForm());
            ((Stage) scene.getWindow()).getIcons().add(new Image(GluonApplication.class.getResourceAsStream("/icon2.png")));
    
    
        }
    }
    

    Then in the constructor of SocketConnection. You can acces the fields like this:

        /*
         * Constructor
         */
        public SocketConnection(View primaryView, View secondaryView) {
    
            /*
             * For secondaryView
             */
            statusTextField = (TextField) secondaryView.lookup("#statusTextField");
            ipAddressTextField = (TextField) secondaryView.lookup("#ipAddressTextField");
            startSignalModeComboBox = (ComboBox<String>) secondaryView.lookup("#startSignalModeComboBox");
            predictHorizonTextField = (TextField) secondaryView.lookup("#predictHorizonTextField");
            controlHorizonTextField = (TextField) secondaryView.lookup("#controlHorizonTextField");
            sampleTimeTextField = (TextField) secondaryView.lookup("#sampleTimeTextField");
            pwmDutyCallTextField = (TextField) secondaryView.lookup("#pwmDutyCallTextField");
            endTimeOfStartSignalTextField = (TextField) secondaryView.lookup("#endTimeOfStartSignalTextField");
            referencePointTextField = (TextField) secondaryView.lookup("#referencePointTextField");
            portTextField = (TextField) secondaryView.lookup("#portTextField");
    
            /*
             * For primaryView
             */
            lineChart = (LineChart<String, Number>) primaryView.lookup("#lineChart");
    
            /*
             * Declare the data object inside the chart
             */
            time_output = new Series<String, Number>();
            lineChart.getData().add(time_output);
    
    
        }