0

I have an application with both MenuBar and ToolBar. I found in ControlsFX documentation that it is possible to define the action event logic in a different class and assign it to buttons, menuitems and togglebuttons define by fxml. More or less like a router in php frameworks(e.g laravel).

Here is the description

An action in JavaFX can be used to separate functionality and state from a control. For example, if you have two or more controls that perform the same function (e.g. one in a Menu and another on a toolbar), consider using an Action object to implement the function. An Action object provides centralized handling of the state of action-event-firing components such as buttons, menu items, etc. The state that an action can handle includes text, graphic, long text (i.e. tooltip text), and disabled.

The problem is that i was not able to get enough info to use it in my application. Here is a simple example i have so far

public class RootController implements Initializable {
@FXML
private MenuItem menuOne;
@FXML
private MenuItem menuTwo;
@FXML
private MenuItem menuThree;
@FXML
private Button tbOne;
@FXML
private Button tbTwo;
@FXML
private Button tbThree;

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}
}

root.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
   <top>
      <VBox BorderPane.alignment="CENTER">
         <children>
            <MenuBar>
          <menus>
            <Menu mnemonicParsing="false" text="File">
              <items>
                <MenuItem fx:id="menuOne" mnemonicParsing="false" text="One" />
              </items>
            </Menu>
            <Menu mnemonicParsing="false" text="Edit">
              <items>
                <MenuItem fx:id="menuTwo" mnemonicParsing="false" text="Two" />
              </items>
            </Menu>
            <Menu mnemonicParsing="false" text="Whatever">
              <items>
                <MenuItem fx:id="menuThree" mnemonicParsing="false" text="Three" />
              </items>
            </Menu>
          </menus>
        </MenuBar>
        <ToolBar prefHeight="40.0" prefWidth="200.0">
          <items>
            <Button fx:id="tbOne" mnemonicParsing="false" text="One" />
              <Button fx:id="tbTwo" layoutX="10.0" layoutY="13.0" mnemonicParsing="false" text="Two" />
              <Button fx:id="tbThree" layoutX="66.0" layoutY="13.0" mnemonicParsing="false" text="Three" />
          </items>
        </ToolBar>
     </children>
  </VBox>
   </top>
</BorderPane>

Main

public class MainApp extends Application {
public static void main(String[] args) throws Exception {launch(args); }

public void start(Stage stage) throws Exception {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/root.fxml"));
    loader.setController(new RootController());
    Scene scene = new Scene((Parent)loader.load(), 400, 200);
    stage.setTitle("ControlFX Action API");
    stage.setScene(scene);
    stage.show();
}
}

AppRouter

public class AppRouter {
public AppRouter(){
    ActionMap.register(this); 
}

public void testOne(){
    System.out.println("testOne");
}

public void testTwo(){
    System.out.println("testTwo");
}

public void testThree(){
    System.out.println("testThree");
}
}

My problem is how to assign the methods in AppRouter to buttons and menuitems in the RootController

Update

I will gladly accept anyother alternative answer too.

ItachiUchiha
  • 36,135
  • 10
  • 122
  • 176
Yunus Einsteinium
  • 1,102
  • 4
  • 21
  • 55

1 Answers1

0

Let's assume that you will create an Instance of AppRouter class in the Application class:

public class MainApp extends Application {

AppRouter appRouter = new AppRouter(); //here................

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

public void start(Stage stage) throws Exception {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/root.fxml"));
    loader.setController(new RootController());
    Scene scene = new Scene((Parent)loader.load(), 400, 200);
    stage.setTitle("ControlFX Action API");
    stage.setScene(scene);
    stage.show();
}
}

Then you can have a method which accepts an AppRouter,in the FXMLController:

public class RootController implements Initializable {
@FXML
private MenuItem menuOne;
@FXML
private MenuItem menuTwo;
@FXML
private MenuItem menuThree;
@FXML
private Button tbOne;
@FXML
private Button tbTwo;
@FXML
private Button tbThree;

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}

public void acceptRouter(AppRouter router){


   //register or call router methods here
  }
}

How to get the controller you just created into the MainApp class?

    FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/root.fxml"));
    loader.setController(new RootController());

    RootController controller = loader.getController(); //simple as this,although check the method name if it is the same cause i added this from phone
    controller.acceptRouter(appRouter);
GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93