JavaFX z Arią - powrót do strony głównej

FXML tutorial (5) – skrypt zewnętrzny

Skrypt nie musi być umieszczony w pliku FXML. Może być skryptem zewnętrznym.

Skrypt outer.groovy
package codes
/**
 * Zwróć uwagę na oznaczenie pakietu.
 * Ten plik zostanie automatycznie (i zawsze) skompilowany do
 * pliku outer.class
 */
def showText1() {
    lab1.setText("Wybrałeś 'Tak'")
}
def showText2() {
    lab1.setText("Wybrałeś 'Nie'")
}
def showText3() {
    lab1.setText("Wybrałeś 'Anuluj'")
}
Plik listing05_fxscript_outer.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?language groovy?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>

<VBox xmlns:fx="http://javafx.com/fxml">
	<Label fx:id="lab1" text="Twoja decyzja?" />
	<HBox fx:id="hbox">
		<Button fx:id="but1" text="Tak" onAction="showText1();" />
		<Button fx:id="but2" text="Nie" onAction="showText2()" />
		<Button fx:id="but3" text="Anuluj" onAction="showText3()" />
	</HBox>
	<fx:script source="../codes/outer.groovy" charset="utf-8"/>
</VBox>

Tutaj pojawia się problem przedstawiony na rys. 1.

Błąd analizatora składni
Błąd analizatora składni

Atrybut charset jest prawidłowy i nie sprawia kłopotu przy uruchamianiu kodu.

Klasa Listing05_fxscript_outer.java

Jest to klasa uruchamiająca.

package codes;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.net.URL;
public class Listing05_fxscript_outer extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        try {
            URL fxmlUrl = this.getClass().getClassLoader()
                    .getResource("resources/listing05_fxscript_outer.fxml");
            VBox root = fxmlUrl != null ? FXMLLoader.load(fxmlUrl) : new VBox();
            Scene scene = new Scene(root, 150, 80);
            stage.setScene(scene);
            stage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Po uruchomieniu kodu pojawia się kolejny błąd:

javafx.fxml.LoadException: 
/C:/Users/Jacek/IdeaProjects/groovylang/out/production/fxmlgroovyscript/resources/listing05_fxscript_outer.fxml:15

	at javafx.fxml@19/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2707)
	at javafx.fxml@19/javafx.fxml.FXMLLoader$ScriptElement.processStartElement(FXMLLoader.java:1606)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2808)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2634)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3331)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3287)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3255)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3227)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3203)
	at javafx.fxml@19/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3196)
	at fxmlgroovyscript/codes.Listing05_fxscript_outer.start(Listing05_fxscript_outer.java:20)
	at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
	at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
	at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
	at javafx.graphics@19/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
	at javafx.graphics@19/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at javafx.graphics@19/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
	at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: javafx.fxml.LoadException: 
/C:/Users/Jacek/IdeaProjects/groovylang/out/production/fxmlgroovyscript/resources/listing05_fxscript_outer.fxml:15

	at javafx.fxml@19/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2707)
	at javafx.fxml@19/javafx.fxml.FXMLLoader$ScriptElement.processStartElement(FXMLLoader.java:1577)
	... 19 more
Caused by: java.io.FileNotFoundException: C:\Users\Jacek\IdeaProjects\groovylang\out\production\fxmlgroovyscript\codes\outer.groovy (Nie można odnaleźć określonego pliku)
	at java.base/java.io.FileInputStream.open0(Native Method)
	at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
	at java.base/java.io.FileInputStream.(FileInputStream.java:158)
	at java.base/java.io.FileInputStream.(FileInputStream.java:112)
	at java.base/sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:86)
	at java.base/sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:189)
	at java.base/java.net.URL.openStream(URL.java:1162)
	at javafx.fxml@19/javafx.fxml.FXMLLoader$ScriptElement.processStartElement(FXMLLoader.java:1564)
	... 19 more

Problemem jest to, że Groovy oczekuje nieskompilowanego (źródłowego) pliku skryptu w folderze out\production\fxmlgroovyscript\codes\ z plikami skompilowanymi, ale kompilator go tam nie umieszcza. Jeżeli ręcznie przeniesiemy plik źródłowy – kod będzie wykonywany prawidłowo.