2013-05-19 8 views
10

I javafx mit fxml entlang bin mit, so dass ich die Controller für die reale Codierung. Ich muss ein paar Operationen auf der Bühne machen, wie zum Beispiel die Position der X- oder Y-Achse. Ich habe versucht, stage.getX() & stage.getY, aber sie funktionieren nicht (der Künstlername ist als der Fehler high-lited). Wie verwende ich solche Funktionen in meinem Controller? Ich habe versucht, dies zu tun in meinem Haupt-Datei:Wie auf der Bühne Funktionen aufzurufen in JavaFX der Controller-Datei

public int locationX = stage.getX(); 

und

public double locationX = stage.getX(); 

Aber es nicht funktioniert, macht stattdessen das gesamte Programm ein großer Fehler.
Also, wie bekomme ich solche Funktionen in meiner Controller-Datei? Muss ich etwas importieren oder etwas auf eine andere Art tun?

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


Ich weiß, dass die "Bühne" fehlt. Aber wie zu bekommen die "Bühne" in meinem Controller?

Antwort

25

Von Ihrem Wurzel Pane in der fxml Datei:

@FXML 
Parent root 

Sie die Bühne, indem von ihm bekommen können:

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

Sie einen Verweis auf Ihre Bühne haben, können Sie tun was du willst.

+0

Immer, wenn ich dies versuchen, der folgende Fehler auftritt: https://docs.google.com/document/d/1-meEWGRc94_RswP966e44tJiLeSWM_x3JQ9i119-kWQ/edit?usp=sharing –

+0

Vielleicht ist ein anderes Problem, öffne eine neue Frage und poste den Code 'DarknessFXMLController' und deine' fxml' Datei. – tarrsalah

+1

@PratikAnand Sie haben 'NPE', weil beim Aufruf von' load() 'keine' stage' an die 'scene' angehängt ist (wobei' load() 'intern' initialize() 'aufruft). –

14

Probenlösung

Sie die Bühne, die Technik von in der Steuerung initialisieren kann mit: Passing Parameters JavaFX FXML.

Hier ist ein Beispielprogramm, das ein Dienstprogrammfenster erstellt, das die X- und Y-Koordinaten des Bildschirms verfolgt, während Sie das Dienstprogrammfenster ziehen. Der Inhalt des Dienstprogrammfensters wird in einem für fxml definierten Fenster gerendert.

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> 

Alternative Lösungen

tarrsalah Antwort nur die Bühne von einer @FXML Komponente immer ist auch ein guter Weg, wenn Sie, dass die Wurzelkomponente des Controllers kennen bereits zu einem hinzugefügt Szene, die bereits zu einer Bühne hinzugefügt wurde (was oft der Fall ist, wenn so etwas wie ein Button Event Handler ausgelöst wird).

Eine andere Möglichkeit, dies zu tun, ist ähnlich der Antwort von tarrsalah, aber ChangeListeners für die scene -Eigenschaft eines @ FXML-Knotens und die window -Eigenschaft der geänderten Szene zu verwenden. Auf diese Weise können Sie Änderungen an Szene und Bühne verfolgen, falls das Fenster in eine neue Szene oder Bühne verschoben wird. Meistens müssen Sie diese Änderungen jedoch nicht verfolgen, da die meisten Fenster nur zu einer einzelnen Szene hinzugefügt werden, die auf einer Bühne bleibt.

Antworten auf weitere Fragen und Kommentare

Kann ich eine einfachere Antwort?

tarrsalah bereits eine einfachere Antwort zur Verfügung gestellt.

Das einzige Problem mit einer einfacheren Antwort in diesem Fall ist, dass es nicht genügend Kontext bietet, um die Antwortlösung zu replizieren und an Ihre Arbeit anzupassen.

Ich machte meine aktuelle Antwort so einfach wie ich konnte, aber leider benötigt sogar die grundlegendste JavaFX FXML-Anwendung einiges an Code und Markup, um zu funktionieren.

Ich bin nur ein Anfänger in Java

nicht FXML verwenden, wenn Sie zuerst beginnen, Ihre ersten Java und JavaFX-Anwendungen zu entwickeln. Stattdessen bleiben Sie einfach mit dem Standard in Ihrem JavaFX-Code, für den es viele weitere tutorials sowie die ausgezeichnete Ensemble Sample zu beziehen gibt.

Vergewissern Sie sich vor Beginn von JavaFX, dass Sie alle Java Tutorial Trails Covering the Basics abgeschlossen haben. Nur die Grundlagen von Java sind erforderlich, um JavaFX zu verwenden, Sie müssen nicht in Java Enterprise Edition verzweigen und können Swing vergessen.

Erwägen Sie die Verwendung von SceneBuilder und FXML für größere Anwendungen, sobald Sie ein paar grundlegende JavaFX-Anwendungen geschrieben haben, einige Layouts nach Java-API handkodiert und ein hohes Maß an Komfort mit den Kerntechnologien erreicht haben. Zu dieser Zeit werden Sie wahrscheinlich feststellen, dass das Lernen von FXML ziemlich einfach ist. FXML-Attribute und -Elemente spiegeln nur die Java-APIs wider.

erklären Sie bitte die anderen als üblich Bits des Codes

kann ich nicht wirklich tun, dass ich weiß nicht, was für Sie ungewöhnlich ist.

Wenn es bestimmte Teile des Codes gibt, die Sie nicht durch Ihr eigenes Wissen oder Forschung verstehen können, create a new StackOverflow question für jedes schwierige Konzept.

+0

Kann ich eine einfachere Antwort bekommen? Ich bin ein Anfänger in Java und bitte erklären Sie die anderen als üblichen Bits Ihres Codes. –

+0

Aktualisierte Antwort zu Pratiks Kommentar. – jewelsea

+0

danke. Ich habe bereits Basis-Java für 1/2 Monat, Swing für später 1/2 und komme schließlich zu FX. Ich habe Code in einfachen Javafx-Programmen (non-fxml) geschrieben. Ich verwende Scenebuilder für fast alle meine fxml-Apps. –

3

Nun, die einfachste Antwort auf diese Frage ...

In Ihrer Hauptklasse eine Instanz erstellen (ein Objekt) Ihre Controller-Klasse:



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

In Ihrem Klasse-Controller Sie stellen eine Methode der "Extraktion" sollte (a Setter):



    private Stage primaryStage; 

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

Und dann können Sie eine ful hinzufügen lscreen Taste;)



    @FXML 
    private Button btnFullScreen = new Button(); 

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

+1

Sie könnten Ihren Fullscreen-Einstellungscode reduzieren: 'primaryStage.setFullScreen (! PrimaryStage.isFullScreen())' – JamEngulfer

+0

True.Danke :)) –

+0

Eine andere Möglichkeit, Stufen zu verwenden, ist mit StageHelper.getStages(). Get (Index) –

1

Dieser Thread ist alt, aber ich entdeckte etwas relevant für sie ganz zufällig. Was ich dachte, war ein Codierungsfehler, der nicht hätte funktionieren sollen, aber es tat es. In der Controller-Klasse deklarieren Sie einfach die folgende Elementvariable:

@FXML private Bühne Bühne;

gab mir Zugriff auf die Bühne in der Steuerung, ähnlich wie ich auf ein Widget im fxml Dokument zugreifen. Ich habe keine Dokumentation gefunden, dass dies der Fall ist, aber ich gebe zu, dass ich zu JavaFX noob bin (obwohl eine alte Hand bei Swing). Aber es scheint zu funktionieren. Vielleicht ist es gefährlich, darauf zu zählen?

1

Mit * .FXML Dateien und Controller und nicht mit Haupt- oder Events, verwenden:

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

Element kann in Ihnen FXML, jede Kontrolle oder Element sein, in meinem Fall ist ein AnchorPane:

@FXML private AnchorPane element; 
0

der beste Ansatz ist es, einen neuen Controller zu erstellen und den stage über den Konstruktor übergeben (nicht fx:controller auf FXML-Datei verwenden), da sonst die stagesein, wenn initialize() aufgerufen wird (zu diesem Moment der Zeit, wenn load()initialize() aufruft, wird keine stage zum scene befestigt, daher die scene ‚s stage ist 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 
    } 
} 
Verwandte Themen