拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 如何使用FXrouter或其他方式手动实体化FXML控制器?

如何使用FXrouter或其他方式手动实体化FXML控制器?

白鹭 - 2022-01-25 2137 0 0

大家下午好。我正在尝试将控制器启动到 FXML 页面,但不确定如何。我目前正在使用 FXRouter GitHub API。

我想将控制器页面系结到 FXML 档案之外的 FXML 页面。我在下面有一个“LoadNewRoute”方法,目前正在这样做,但我想改进这一点,因此它将控制器分配给外部的 FXML 页面。做这个的最好方式是什么?

加载页面的方法

private static void loadNewRoute(RouteScene route) throws IOException {
        // get Main Class package name to get correct files path

        String pathRef = mainRef.getClass().getPackage().getName();


        // set FXRouter current route reference
        currentRoute = route;

        // create correct file path.  "/" doesn't affect any OS
        String scenePath = "/"   pathRef   "/"   route.scenePath;


        // load .fxml resource
        FXMLLoader loader = new FXMLLoader(new Object() { }.getClass().getResource(scenePath));
        Parent resource = loader.load();




      //  resource.setController(BuyController);

        // set window title from route settings or default setting
        window.setTitle(route.windowTitle);
        // set new route scene
        window.setScene(new Scene(resource, route.sceneWidth, route.sceneHeight));
        // show the window
        window.show();

        // set scene animation
        routeAnimation(resource);
    }

FXML 页面-

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>

<AnchorPane xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.gradle.Controllers.BuyController" >

    <MenuBar layoutX="676.0" layoutY="2.0">
        <Menu mnemonicParsing="false" text="Pages">
            <MenuItem mnemonicParsing="false" onAction="#SwitchToMainScene" text="Home" />
            <MenuItem mnemonicParsing="false" onAction="#SwitchToBuyScene" text="Buy" />
            <MenuItem mnemonicParsing="false" onAction="#SwitchToSellScene" text="Sell" />
        </Menu>
        <Menu mnemonicParsing="false" text="Options">
            <MenuItem mnemonicParsing="false" onAction="#CloseApp" text="Exit" />
            <MenuItem mnemonicParsing="false" onAction="#SwitchToProfileScene" text="Profile" />
        </Menu>
    </MenuBar>
    <Pane layoutX="14.0" layoutY="67.0" prefHeight="200.0" prefWidth="200.0">
        <CheckBox layoutX="7.0" layoutY="116.0" mnemonicParsing="false" prefHeight="17.0" prefWidth="82.0" text="DogeCoin" />
        <CheckBox layoutX="7.0" layoutY="153.0" mnemonicParsing="false" prefHeight="17.0" prefWidth="72.0" text="Bitcoin" />
        <CheckBox layoutX="7.0" layoutY="83.0" mnemonicParsing="false" text="Etherium" />
        <Label layoutX="27.0" layoutY="26.0" text="Select your CryptoCurrency" />
    </Pane>
    <Pane layoutX="528.0" layoutY="-1.0" prefHeight="37.0" prefWidth="272.0">
        <Button layoutX="222.0" layoutY="-1.0" mnemonicParsing="false" onAction="#CloseApp" prefHeight="30.0" prefWidth="50.0" text="Exit" />
        <Button layoutX="166.0" layoutY="-1.0" mnemonicParsing="false" onAction="#SwitchToProfileScene" prefHeight="30.0" prefWidth="56.0" text="Profile" />
        <Button layoutX="118.0" layoutY="-1.0" mnemonicParsing="false" onAction="#SwitchToSellScene" prefHeight="30.0" prefWidth="48.0" text="Sell" />
        <Button layoutX="70.0" layoutY="-1.0" mnemonicParsing="false" onAction="#SwitchToBuyScene" prefHeight="30.0" prefWidth="48.0" text="Buy" />
        <Button layoutX="14.0" layoutY="-1.0" mnemonicParsing="false" onAction="#SwitchToMainScene" prefHeight="30.0" prefWidth="56.0" text="Home" />
    </Pane>
    <Pane layoutX="300.0" layoutY="88.0" prefHeight="200.0" prefWidth="200.0">
        <RadioButton layoutX="13.0" layoutY="38.0" mnemonicParsing="false" text="Amount in coin" />
        <RadioButton layoutX="13.0" layoutY="67.0" mnemonicParsing="false" text="Amount in cash" />
        <TextField layoutX="13.0" layoutY="139.0" />
        <Label layoutX="-1.0" prefHeight="34.0" prefWidth="200.0" text="Choose type of buying, and enter amount" wrapText="true" />
    </Pane>
    <Button layoutY="-1.0" mnemonicParsing="false" onAction="#BackButton" prefHeight="30.0" prefWidth="64.0" text="Back" />
    <Button layoutX="237.0" layoutY="447.0" mnemonicParsing="false" onAction="#BuyButton" prefHeight="82.0" prefWidth="278.0" text="Buy">
        <font>
          <Font size="31.0" />
        </font>
     </Button>
</AnchorPane>

控制器-

   package com.gradle.Controllers;
   import com.gradle.Controller;
  import com.gradle.FXRouter;
  import javafx.event.ActionEvent;
  import javafx.fxml.FXMLLoader;

  import java.io.IOException;

  public class BuyController extends com.gradle.Controller {

  public void example () {

  }

    

家庭控制器

public class HomeController extends com.gradle.Controller {


    public void SwitchToMainScene (ActionEvent event) throws IOException {
        FXRouter.goTo("Home", new HomeController());}

    public void SwitchToBuyScene (ActionEvent event) throws IOException {
        FXRouter.goTo("Buy", new BuyController());}

    public void SwitchToSellScene (ActionEvent event) throws IOException {
        FXRouter.goTo("Sell", new SellController());}

    public void SwitchToProfileScene (ActionEvent event) throws IOException {
        FXRouter.goTo("Profile", new ProfileController());}

    @Override
    public void initilize(URL url, ResourceBundle rb) {

    }
}

称呼-

 FXRouter.goTo("Home", new HomeController());

FXML-

  <Button fx:id="exit" layoutX="222.0" layoutY="-1.0" mnemonicParsing="false" onAction="#CloseApp" prefHeight="30.0" prefWidth="50.0" text="Exit" />
        <Button layoutX="166.0" layoutY="-1.0" mnemonicParsing="false" onAction="#SwitchToProfileScene" prefHeight="30.0" prefWidth="56.0" text="Profile" />
        <Button layoutX="118.0" layoutY="-1.0" mnemonicParsing="false" onAction="#SwitchToSellScene" prefHeight="30.0" prefWidth="48.0" text="Sell" />
        <Button layoutX="70.0" layoutY="-1.0" mnemonicParsing="false" onAction="#SwitchToBuyScene" prefHeight="30.0" prefWidth="48.0" text="Buy" />
        <Button layoutX="14.0" layoutY="-1.0" mnemonicParsing="false" onAction="#SwitchToMainScene" prefHeight="30.0" prefWidth="56.0" text="Home" />
    </Pane>
   <Button layoutY="-1.0" mnemonicParsing="false" onAction="#BackButton" prefHeight="30.0" prefWidth="64.0" text="Back" />
</AnchorPane>

所有 onAction 都给我错误,它找不到呼叫

uj5u.com热心网友回复:

没有 FXMLRouter

在这个问题的答案中演示了为 FXML(没有 FXMLRouter 库)手动配置控制器的标准方法:

  • JavaFX - 如何在 fxml 控制器初始化期间设定值

请注意,如果您手动设定控制器,你应该还提供了一个fx:controller在FXML档案属性。

如果您没有使用 FXMLRouter 库,那么只需按照链接问题的答案中的示例进行操作,而忽略此答案的其余部分。


使用 FXMLRouter

我看了代码,FXMLRouter不能做你想做的。

它使用静态加载功能如果你想设定一个你创建的控制器,那么你必须使用一个加载器实体,如先前参考的答案中所示。

整个路由器只是一类。

如果你想使用它:

  1. 将源代码复制到您的项目中。

  2. 修改loadNewRoute方法(以及呼叫它的方法)以传入您创建的控制器。

    • 如果您想保留当前的公共界面,您可以这样做并添加新的多载界面,这些界面也接受您本地构造的控制器类。
  3. 如果手动设定控制器,请更改实作以创建新的 FXMLLoader 并在新的加载器实体上设定控制器,而不是使用静态加载方法。

先前参考的答案中演示了对加载实作所需的修改。

或者,您可以修改 FXMLLoader 代码以使用本答案中其他地方讨论的自定义 FXML 控制器工厂方法。

FXMLRouter 实作示例

这不是我的代码,我已经根据此答案中先前的修改建议对其进行了修改,原始代码和许可证信息位于:

  • https://github.com/Marcotrombino/FXRouter

我根本没有测验过这些修改,也不保证它们会起作用。代码仅作为示例提供。

import java.io.IOException;
import java.util.AbstractMap;
import java.util.HashMap;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Parent;
import javafx.util.Duration;
import javafx.animation.FadeTransition;

/**
 * FXRouter allows to manage scenes switching on JavaFX Application with an easy API
 * Inspired by Angular JS $routeProvider
 * @author Marco Trombino
 * @version 1.0.0
 */
public final class FXRouter {
    private static final String WINDOW_TITLE = "";
    private static final Double WINDOW_WIDTH = 800.0;
    private static final Double WINDOW_HEIGHT = 600.0;
    private static final Double FADE_ANIMATION_DURATION = 800.0;

    // FXRouter Singleton
    private static FXRouter router;
    // FXRouter Main Class reference to get main package
    private static Object mainRef;
    // FXRouter Application Stage reference to set scenes
    private static Stage window;

    // Application Stage title
    private static String windowTitle;
    // Application Stage size
    private static Double windowWidth;
    private static Double windowHeight;

    // routes switching animation
    private static String animationType;
    private static Double animationDuration;

    // FXRouter routes map
    private static AbstractMap<String, RouteScene> routes = new HashMap<>();
    // FXRouter current route
    private static RouteScene currentRoute;

    /**
     * FXRouter Inner Class used into routes map
     */
    private static class RouteScene {
        // route .fxml Scene path
        private String scenePath;
        // Scene (Stage) title
        private String windowTitle;
        private double sceneWidth;
        private double sceneHeight;
        // route data passed from goTo()
        private Object data;

        private RouteScene(String scenePath) {
            this(scenePath, getWindowTitle(), getWindowWidth(), getWindowHeight());
        }

        private RouteScene(String scenePath, String windowTitle) {
            this(scenePath, windowTitle, getWindowWidth(), getWindowHeight());
        }

        private RouteScene(String scenePath, double sceneWidth, double sceneHeight) {
            this(scenePath, getWindowTitle(), sceneWidth, sceneHeight);
        }

        /** Route scene constructor
         * @param scenePath: .FXML scene file
         * @param windowTitle: Scene (Stage) title
         * @param sceneWidth: Scene Width
         * @param sceneHeight: Scene Height
         */
        private RouteScene(String scenePath, String windowTitle, double sceneWidth, double sceneHeight) {
            this.scenePath = scenePath;
            this.windowTitle = windowTitle;
            this.sceneWidth = sceneWidth;
            this.sceneHeight = sceneHeight;
        }

        private static String getWindowTitle() {
            return FXRouter.windowTitle != null ? FXRouter.windowTitle : WINDOW_TITLE;
        }

        private static double getWindowWidth() {
            return FXRouter.windowWidth != null ? FXRouter.windowWidth : WINDOW_WIDTH;
        }

        private static double getWindowHeight() {
            return FXRouter.windowHeight != null ? FXRouter.windowHeight : WINDOW_HEIGHT;
        }
    }

    /**
     * FXRouter constructor kept private to apply Singleton pattern
     */
    private FXRouter() {}

    public static void bind(Object ref, Stage win) {
        checkInstances(ref, win);
    }

    public static void bind(Object ref, Stage win, String winTitle) {
        checkInstances(ref, win);
        windowTitle = winTitle;
    }

    public static void bind(Object ref, Stage win, double winWidth, double winHeight) {
        checkInstances(ref, win);
        windowWidth = winWidth;
        windowHeight = winHeight;
    }

    /** FXRouter binder with Application Stage and main package
     * @param ref: Main Class reference
     * @param win: Application Stage
     * @param winTitle: Application Stage title
     * @param winWidth: Application Stage width
     * @param winHeight: Application Stage height
     */
    public static void bind(Object ref, Stage win, String winTitle, double winWidth, double winHeight) {
        checkInstances(ref, win);
        windowTitle = winTitle;
        windowWidth = winWidth;
        windowHeight = winHeight;
    }

    /** set FXRouter references only if they are not set yet
     * @param ref: Main Class reference
     * @param win: Application Stage
     */
    private static void checkInstances(Object ref, Stage win) {
        if(mainRef == null)
            mainRef = ref;
        if(router == null)
            router = new FXRouter();
        if(window == null)
            window = win;
    }

    public static void when(String routeLabel, String scenePath) {
        RouteScene routeScene = new RouteScene(scenePath);
        routes.put(routeLabel, routeScene);
    }

    public static void when(String routeLabel, String scenePath, String winTitle) {
        RouteScene routeScene = new RouteScene(scenePath, winTitle);
        routes.put(routeLabel, routeScene);
    }

    public static void when(String routeLabel, String scenePath, double sceneWidth, double sceneHeight) {
        RouteScene routeScene = new RouteScene(scenePath, sceneWidth, sceneHeight);
        routes.put(routeLabel, routeScene);
    }

    /** Define a FXRouter route
     * @param routeLabel: Route label identifier
     * @param scenePath: .FXML scene file
     * @param winTitle: Scene (Stage) title
     * @param sceneWidth: Scene Width
     * @param sceneHeight: Scene Height
     */
    public static void when(String routeLabel, String scenePath, String winTitle, double sceneWidth, double sceneHeight) {
        RouteScene routeScene = new RouteScene(scenePath, winTitle, sceneWidth, sceneHeight);
        routes.put(routeLabel, routeScene);
    }

    public static void goTo(String routeLabel) throws IOException {
        goTo(routeLabel, null, null);
    }

    public static void goTo(String routeLabel, Object data) throws IOException {
        goTo(routeLabel, data, null);
    }

    /** Switch between FXRouter route and show corresponding scenes
     * @param routeLabel: Route label identifier
     * @param data: Data passed to route
     * @oaram controller: Controller instance to use.
     * @throws Exception: throw FXMLLoader exception if file is not loaded correctly
     */
    public static void goTo(String routeLabel, Object data, Object controller) throws IOException {
        // get corresponding route
        RouteScene route = routes.get(routeLabel);
        // set route data
        route.data = data;
        loadNewRoute(route, controller);
    }

    /** Helper method of goTo() which load and show new scene
     * @throws Exception: throw FXMLLoader exception if file is not loaded correctly
     */
    private static void loadNewRoute(RouteScene route, Object controller) throws IOException {
        // get Main Class package name to get correct files path
        String pathRef = mainRef.getClass().getPackage().getName();

        // set FXRouter current route reference
        currentRoute = route;

        // create correct file path.  "/" doesn't affect any OS
        String scenePath = "/"   pathRef   "/"   route.scenePath;

        // load .fxml resource
        FXMLLoader loader = new FXMLLoader();
        loader.setController(controller);
        Parent resource = loader.load(new Object() { }.getClass().getResource(scenePath));

        // set window title from route settings or default setting
        window.setTitle(route.windowTitle);
        // set new route scene
        window.setScene(new
							
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *