it-swarm.com.de

Aufrufen von Funktionen auf der Bühne in der JavaFX-Controller-Datei

Ich benutze javafx zusammen mit mit fxml , also benutze ich den Controller für die eigentliche Codierung . Ich muss ein paar Operationen auf der Bühne ausführen, z. B. die X- oder Y-Achsenposition ermitteln. Ich habe stage.getX() & stage.getY ausprobiert, aber sie funktionieren nicht (der Stufenname wird als Fehler hervorgehoben). Wie verwende ich solche Funktionen in meinem Controller? Ich habe versucht, dies in meiner Hauptdatei zu tun:

 public int locationX = stage.getX();

und

public double locationX = stage.getX();

Aber es funktioniert nicht, sondern macht das ganze Programm zu einem großen Fehler.
Wie kann ich solche Funktionen in meiner Controller-Datei ausführen? Muss ich etwas importieren oder etwas wie oben auf andere Weise tun?

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


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

10
Pratik Anand

In Ihrem root Bereich in der Datei fxml:

@FXML
Parent root

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

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

Sie haben einen Bezug zu Ihrer Bühne, Sie können tun, was Sie wollen.

25
tarrsalah

Probelösung

Sie können die Bühne im Controller wie folgt initialisieren: Parameter übergeben JavaFX FXML .

In diesem Beispielprogramm wird ein Hilfsprogrammfenster erstellt, in dem die x- und y-Koordinaten des Bildschirms aufgezeichnet werden, während Sie das Hilfsprogrammfenster verschieben. Der Inhalt des Hilfsprogrammfensters wird in einem von fxml definierten Bereich 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

tarrsalahs Antwort, nur die Bühne von einer @FXML-Komponente abzurufen, ist auch eine gute Möglichkeit, wenn Sie wissen, dass die Root-Komponente des Controllers bereits einer Szene hinzugefügt wurde, die bereits einer Bühne hinzugefügt wurde (was häufig der Fall ist, wenn etwas passiert) wie ein Knopf Eventhandler wird ausgelöst).

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

Antworten auf zusätzliche Fragen und Kommentare

Kann ich eine einfachere Antwort bekommen?

tarrsalah lieferte bereits eine einfachere Antwort.

Das einzige Problem bei einer einfacheren Antwort besteht in diesem Fall darin, dass möglicherweise nicht genügend Kontext bereitgestellt wird, damit Sie die Lösung der Antwort replizieren und an Ihre Arbeit anpassen können.

Ich habe meine aktuelle Antwort so einfach wie möglich gemacht, aber leider erfordert auch die einfachste JavaFX FXML-Anwendung einiges an Code und Markup, um zu funktionieren.

Ich bin ein Anfänger in Java

Verwenden Sie FXML nicht, wenn Sie mit der Entwicklung Ihrer ersten Java- und JavaFX-Anwendungen beginnen. Halten Sie sich stattdessen einfach an die standardmäßige Java-API in Ihrem JavaFX-Code, für die es viele weitere Tutorials sowie das exzellente Ensemble-Beispiel gibt.

Vergewissern Sie sich, bevor Sie mit JavaFX beginnen, dass Sie alle Java Tutorial Trails abgeschlossen haben, die die Grundlagen abdecken . Für den Start von JavaFX sind nur die Grundlagen von Java erforderlich. Sie müssen sich nicht mit dem Erlernen von Java Enterprise Edition befassen und können Swing vergessen.

Ziehen Sie die Verwendung von SceneBuilder und FXML für größere Anwendungen in Betracht, nachdem Sie einige grundlegende JavaFX-Anwendungen geschrieben, einige Layouts gemäß der Java-API handcodiert und mit den Kerntechnologien ein gewisses Maß an Komfort erreicht haben. Zu diesem Zeitpunkt werden Sie wahrscheinlich feststellen, dass das Erlernen von FXML recht einfach ist. FXML-Attribute und -Elemente spiegeln nur die Java-APIs wider.

bitte erläutern Sie die nicht üblichen Teile Ihres Codes

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

Wenn es bestimmte Teile des Codes gibt, die Sie aufgrund Ihrer eigenen Kenntnisse oder Recherchen nicht verstehen können, erstellen Sie eine neue StackOverflow-Frage für jedes schwierige Konzept.

14
jewelsea

Nun, die einfachste Antwort darauf ...

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



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

In Ihrer Klasse Controller sollten Sie eine Methode zur "Extraktion" (einen Setter) angeben:



    private Stage primaryStage;

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

Und dann können Sie eine Vollbild-Schaltfläche hinzufügen;)



    @FXML
    private Button btnFullScreen = new Button();

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

3

Verwenden Sie bei * .FXML-Dateien und Controllern und nicht bei Main oder Events Folgendes:

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

element, kann ein beliebiges Steuerelement oder Element in Ihrer FXML sein, in meinem Fall ein AnchorPane:

@FXML  private AnchorPane element;
1

Dieser Thread ist alt, aber ich habe zufällig etwas Passendes entdeckt. Was ich dachte, war ein Codierungsfehler, der eigentlich nicht hätte funktionieren sollen, aber es tat es. Deklarieren Sie in der Controller-Klasse einfach die folgende Member-Variable:

@FXML private Stage stage;

ermöglicht mir den Zugriff auf die Bühne im Controller, ähnlich wie ich Zugriff auf ein Widget im FXML-Dokument habe. Ich habe keine Dokumentation gefunden, dass dies der Fall ist, aber ich gebe zu, ich bin kein JavaFX-Neuling (obwohl ein alter Hase bei Swing). Aber es scheint zu funktionieren. Vielleicht ist es aber gefährlich, sich darauf zu verlassen?

1
Paul

Der beste Ansatz ist, einen neuen Controller zu erstellen und die stage über den Konstruktor zu übergeben (verwenden Sie nicht fx:controller Für FXML-Dateien), andernfalls lautet die stagenull, wenn initialize() aufgerufen wird (In diesem Moment, wenn load()initialize() aufruft, ist dem stage kein scene zugeordnet. ], daher ist scene des stagenull).

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
    }
}
0
Eng.Fouad