10

我使用 javafx和 fxml,所以我使用控制器进行真正的编码。我需要在舞台上做一些操作,比如获取它的 x 轴或 y 轴位置。我尝试过stage.getX()& stage.getY,但它们不起作用(舞台名称高亮显示为错误)。如何在我的控制器中使用这些功能?我尝试在我的主文件中这样做:

 public int locationX = stage.getX();


public double locationX = stage.getX();

但它不起作用,反而使整个程序出现了一个大错误。
那么如何在我的控制器文件中执行这些功能呢?我是否需要以其他方式导入某些内容或执行上述操作?

error: cannot find symbol
    locationX = stage.getX();
symbol:   variable stage
location: class FXMLController


我知道缺少“舞台”。但是如何在我的控制器中获得“舞台”?

4

6 回答 6

25

从文件中的窗格fxml

@FXML
Parent root

您可以通过以下方式从中获得舞台:

Stage stage = (Stage) root.getScene().getWindow()

你有你的舞台参考,你可以做你想做的事。

于 2013-05-20T16:47:07.733 回答
14

样品溶液

您可以使用以下技术初始化控制器中的阶段:传递参数 JavaFX FXML

这是一个示例程序,它创建一个实用程序窗口,当您拖动实用程序窗口时,它会跟踪屏幕的 x 和 y 坐标。实用程序窗口的内容呈现在 fxml 定义的窗格中。

舞台坐标

StageTrackingSample.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.*;
import javafx.stage.*;

public class StageTrackingSample extends Application {

  @Override public void start(final Stage stage) throws Exception {
    final FXMLLoader loader = new FXMLLoader(
      getClass().getResource(
        "stagetracking.fxml"
      )
    );

    final Parent root = (Parent) loader.load();
    final StageTrackingController controller = loader.getController();
    controller.initData(stage);

    stage.initStyle(StageStyle.UTILITY);
    stage.setResizable(false);
    stage.setScene(new Scene(root));
    stage.show();
  }

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

StageTrackingController.java

import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.stage.Stage;

public class StageTrackingController {
  @FXML private Label stageX;
  public void initialize() {}  
  public void initData(final Stage stage) {
    stageX.textProperty().bind(
      Bindings.format(
        "(%1$.2f, %2$.2f)", 
        stage.xProperty(), 
        stage.yProperty()
      )
    );
  }
}

stagetracking.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="30" minWidth="100" xmlns:fx="http://javafx.com/fxml" fx:controller="test.StageTrackingController">
  <Label fx:id="stageX" layoutX="0" layoutY="0"/>
</AnchorPane>

替代解决方案

如果您知道控制器的根组件已经添加到已经添加到舞台的场景中,那么 tarrsalah 刚刚从 @FXML 组件获取舞台的答案也是一个好方法(这通常是在某些情况下就像一个按钮事件处理程序被触发)。

另一种方法类似于 tarrsalah 的答案,但要在 @FXML 节点的场景属性和已更改场景的窗口属性上使用 ChangeListeners。这使您可以跟踪对场景和舞台的更改,以防窗格移动到新的场景或舞台。大多数情况下,您不需要跟踪这些更改,因为大多数窗格只是添加到单个场景中,该场景保持在一个阶段。

其他问题和评论的答案

我能得到一个更简单的答案吗?

tarrsalah 已经提供了一个更简单的答案。

在这种情况下,简单答案的唯一问题是它可能无法提供足够的上下文来复制答案的解决方案并使其适应您的工作。

我尽可能简单地回答了当前的答案,但不幸的是,即使是最基本的 JavaFX FXML 应用程序也需要相当多的代码和标记才能工作。

我只是java的初学者

刚开始开发初始 Java 和 JavaFX 应用程序时,不要使用 FXML。相反,只需在您的 JavaFX 代码中坚持使用标准Java API,还有更多教程以及优秀的Ensemble Sample可供参考。

确保在开始 JavaFX 之前,您已经完成了涵盖基础知识的所有 Java Tutorial Trails。开始使用 JavaFX 只需要 Java 的基础知识,您不需要分支到学习 Java Enterprise Edition 并且可以忘记 Swing。

一旦您编写了一些基本的 JavaFX 应用程序、根据 Java API 对一些布局进行手工编码并对核心技术达到一定程度的舒适度,就可以考虑将SceneBuilder和 FXML 用于大型应用程序。那时您可能会发现学习 FXML 非常简单。FXML 属性和元素只是 Java API 的反映。

请解释您的代码中不寻常的部分

我真的不能那样做,因为我不知道你有什么不寻常的地方。

如果您通过自己的知识或研究无法理解代码的某些特定部分,请为每个困难的概念创建一个新的 StackOverflow 问题。

于 2013-05-20T17:47:21.523 回答
3

嗯,最简单的答案...

在您的Main 类中创建 Controller 类的实例(对象):



    FXMLLoader loader = new FXMLLoader(getClass().getResource("Example.fxml"));
    MyController controller = loader.getController();
    controller.setStage(this.stage);

在您的Controller 类中,您应该放置一个“提取”方法(setter):



    private Stage primaryStage;

    public void setStage(Stage stage) {
         this.primaryStage = stage;
    }

然后你可以添加一个全屏按钮;)



    @FXML
    private Button btnFullScreen = new Button();

    public void setFullscreen(ActionEvent event){       
         if(primaryStage.isFullScreen()){
              primaryStage.setFullScreen(false);
         } else {
              primaryStage.setFullScreen(true);
         }
    }

于 2014-04-09T03:37:05.280 回答
1

这个线程很旧,但我偶然发现了一些与它相关的东西。我认为是一个不应该起作用的编码错误,但它确实起作用了。在控制器类中,只需声明以下成员变量:

@FXML 私有 Stage 阶段;

让我可以访问控制器中的舞台,就像我可以访问 fxml 文档中的小部件一样。我还没有找到任何文档证明是这种情况,但我承认我对 JavaFX 不熟悉(虽然是 Swing 的老手)。但它似乎工作。也许指望它是危险的?

于 2015-09-16T22:21:51.120 回答
1

使用 *.FXML 文件和控制器而不是 Main 或 Events,使用这个:

@FXML private Stage stage;
stage = (Stage) elemen.getScene().getWindow();

元素,可以是 FXML 中的任何控件或元素,在我的例子中是 AnchorPane:

@FXML  private AnchorPane element;
于 2016-03-07T16:58:57.817 回答
0

最好的方法是创建一个新的控制器并通过stage构造函数传递(不要fx:controller在 FXML 文件上使用),否则stage将在null何时initialize()被调用(那时,当load()调用时initialize(),没有stage附加到scene,因此scenestage) null

public class AppEntryPoint extends Application
{
    private FXMLLoader loader;

    @Override
    public void init() throws Exception
    {
        loader = new FXMLLoader(getClass().getResource("path-to-fxml-file"));
    }

    @Override
    public void start(Stage initStage) throws Exception
    {
        MyController controller = new MyController(initStage);
        loader.setController(controller);
        Scene scene = loader.load();
        initStage.setScene(scene);
        initStage.show();
    }

    public static void main(String[] args)
    {
        launch(args);
    }
}
public class MyController
{
    private Stage stage;

    @FXML private URL location;
    @FXML private ResourceBundle resources;

    public MyController(Stage stage)
    {
        this.stage = stage;
    }

    @FXML
    private void initialize()
    {
        // You have access to the stage right here
    }
}
于 2016-06-27T06:29:04.970 回答