2013-05-19 34 views
10

我使用JavaFX一起與FXML,所以我用了控制器爲實數編碼。我需要在舞臺上做一些操作,例如獲取其x或y軸位置。我嘗試過stage.getX() & stage.getY,但它們不起作用(舞臺名稱被誤認爲是錯誤的)。我如何在控制器中使用這些功能?我試圖在我的主文件,這樣做:如何調用舞臺上的功能JavaFX中的控制器文件

public int locationX = stage.getX(); 


public double locationX = stage.getX(); 

但它不工作,而不是讓整個節目的一個大錯誤。
那麼我如何才能在我的控制器文件中做這樣的功能?我需要導入一些東西還是以另一種方式做類似上面的事情?

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


我知道 「舞臺」 丟失。但如何在我的控制器中獲得「舞臺」?

回答

25

fxml文件的窗格:

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

你有你的舞臺的引用,你可以這樣做:

@FXML 
Parent root 

你可以從它由獲得階段你想要什麼。

+0

每當我試試這個,會出現以下錯誤: https://docs.google.com/document/d/1-meEWGRc94_RswP966e44tJiLeSWM_x3JQ9i119-kWQ/edit?usp=sharing –

+0

也許是另一個問題,請打開一個新問題併發布'DarknessFXMLController'和您的'fxml'文件的代碼。 – tarrsalah

+1

@PratikAnand你得到'NPE'是因爲在調用'load()'('load()'在內部調用'initialize()'''時''stage'不會附加到'scene'。 –

14

樣品溶液

您可以使用該技術從控制器初始化階段:Passing Parameters JavaFX FXML

下面是一個示例程序,它創建一個實用程序窗口,用於在拖動實用程序窗口時跟蹤屏幕的x和y座標。實用程序窗口的內容在fxml定義的窗格中呈現。

stagecoords

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> 

替代解決方案

的從@FXML組件剛剛起步的階段tarrsalah的回答也是一個很好的方式,如果你知道控制器的根組件已添加到已經被添加到舞臺的場景(這通常是在類似按鈕事件處理程序的情況下被觸發的情況)。

另一種做法與tarrsalah的答案類似,但在@FXML節點的scene屬性和更改場景的window屬性上使用ChangeListeners。這使您可以跟蹤對場景和舞臺的更改,以防將窗格移動到新的場景或舞臺。大多數情況下,您不需要跟蹤這些更改,因爲大多數窗格只會添加到停留在一個舞臺上的單個場景中。

回答更多的問題並評論

我可以得到一個簡單的答案嗎?

tarrsalah已經提供了一個更簡單的答案。

在這種情況下,答案更簡單的唯一問題是,它可能無法提供足夠的上下文,以便您複製答案的解決方案並將其適用於您的工作。

我儘可能簡單地回答了當前的答案,但不幸的是,即使是最基本的JavaFX FXML應用程序也需要相當多的代碼和標記才能工作。

我在Java

僅僅初學者不要使用FXML當你第一次開始開發您最初的Java和JavaFX應用程序。相反,只需在您的JavaFX代碼中使用標準Java API即可,其中還有很多tutorials以及優秀的Ensemble Sample可供參考。

請確保在開始JavaFX之前,您已完成所有Java Tutorial Trails Covering the Basics。只有Java的基礎知識才能開始使用JavaFX,您不需要分支學習Java企業版,就可以忘記Swing。

一旦您編寫了幾個基本的JavaFX應用程序,根據Java API手動編碼了一些佈局,並且達到了核心技術的舒適程度,則可以考慮在較大的應用程序中使用SceneBuilder和FXML。那時你可能會發現學習FXML非常簡單。 FXML屬性和元素只是Java API的反映。

請解釋一下你的代碼的其他-比平常位

我真的不能做,因爲我不知道什麼是不尋常的你。

如果您通過自己的知識或研究無法瞭解代碼的某些特定部分,則可針對每個困難的概念使用create a new StackOverflow question

+0

我可以得到更簡單的答案嗎?我在java中只是初學者,請解釋代碼中的其他部分。 –

+0

解決Pratik評論的最新答案。 – jewelsea

+0

謝謝。我已經練習了1/2個月的基本Java,稍後再練習1/2,最後來到fx。我曾經在簡單的javafx(非fxml)程序中編寫代碼。我幾乎所有的fxml應用程序都使用scenebuilder。 –

3

好,最簡單的問題的答案......

在你主類創建控制器類的一個實例(對象):



    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; 
    } 

然後你可以添加一個ful )屏幕上的按鈕;)



    @FXML 
    private Button btnFullScreen = new Button(); 

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

+1

您可以減少全屏設置代碼:'primaryStage.setFullScreen(!primaryStage.isFullScreen())' – JamEngulfer

+0

True。Thanx :)) –

+0

另一種使用階段的方式是 StageHelper.getStages()。get(index) –

1

這個線程很舊,但我偶然發現了一些與它相關的東西。我認爲是一個編碼錯誤,應該不起作用,但它確實如此。在控制器類中,只需聲明以下成員變量:

@FXML private stage stage;

讓我可以訪問控制器中的舞臺,就像我可以訪問fxml文檔中的小部件一樣。我還沒有找到任何文檔,但我承認我不喜歡JavaFX(儘管是Swing的老手)。但它似乎工作。可能依靠它是危險的嗎?

1

隨着* .FXML文件和控制器和不能與主或活動,使用此:

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

元素,可以在你任何控制或元素FXML,於我而言是一個AnchorPane:

@FXML private AnchorPane element; 
0

,最好的方法是創建一個新的控制器,通過構造傳遞stage(不要FXML文件中使用fx:controller),否則stagenullinitialize()被調用(在時間那一刻,當load()調用initialize(),沒有stage附接到scene,因此scenestagenull)。

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 
    } 
} 
相關問題