大家下午好。我正在尝试将控制器启动到 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不能做你想做的。
它使用静态加载功能。如果你想设定一个你创建的控制器,那么你必须使用一个加载器实体,如先前参考的答案中所示。
整个路由器只是一类。
如果你想使用它:
将源代码复制到您的项目中。
修改loadNewRoute方法(以及呼叫它的方法)以传入您创建的控制器。
- 如果您想保留当前的公共界面,您可以这样做并添加新的多载界面,这些界面也接受您本地构造的控制器类。
如果手动设定控制器,请更改实作以创建新的 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 评论