Gamer818
Gamer818

Reputation: 112

Not able to use stage in main class from controller

I'm trying to make a screen recorder using JavaFX. I was googling how to make one, when I saw this article, I tried it out and really liked it, so I decided to make a JavaFX FXML application with the code it provided.

@FXML
void startOnAction(ActionEvent event) {
    FXMLDocumentController FXML = new FXMLDocumentController();
    FXML.console.setText("######### Starting Screen Recorder #########");
    try {
        Thread.sleep(250);
    } catch (InterruptedException  ex) {
    }
    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    FXML.console.appendText("Your Screen [Width, Height]: " + "[" + screen.getWidth() + "," + screen.getHeight() + "]\nWhen the Recording starts, this window will minimize, to stop them recording, open this window.");
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
    }
    FXML.console.appendText("The recording will start in 5 seconds");
    int num = 5;
    for (int i = 0; i <= 5; i++) {
        System.out.print(num);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
        }
        num = num - 1;
    }
    FXML.console.appendText("Start!");
    File f = new File(store);
    if (!f.exists()) {
        f.mkdir();
    }
    startRecord();
    Recorder R = new Recorder();
    R.stage.setIconified(true);
    R.stage.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
        focusState(newValue);
    });
}

This is a method in an FXMLDocumentController, I want to make my TextArea with the variable of 'console' print out the text I want it to print out.

However, all the lines where I make use an object, these FXMLDocumentController FXML = new FXMLDocumentController(); and Recorder R = new Recorder(); There is an error.

Here is the error:

    Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8413)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
    ... 48 more
Caused by: java.lang.NullPointerException
    at recorder.FXMLDocumentController.startOnAction(FXMLDocumentController.java:127)
    ... 58 more

Line 127 is `Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8413)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
    ... 48 more
Caused by: java.lang.NullPointerException
    at recorder.FXMLDocumentController.startOnAction(FXMLDocumentController.java:127)
    ... 58 more`

Line 127 is this line 4, on the code I posted above.


Full code below...

Main class:

    package recorder;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Recorder extends Application {

    public Stage stage;

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);
        stage.setResizable(false);
        stage.setScene(scene);
        stage.show();
    }

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

}

FXML document:

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="639.0" prefWidth="578.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="recorder.FXMLDocumentController">
    <columnConstraints>
        <ColumnConstraints hgrow="SOMETIMES" minWidth="578.0" prefWidth="578.0" />
    </columnConstraints>
    <rowConstraints>
        <RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="95.0" vgrow="SOMETIMES" />
        <RowConstraints maxHeight="245.0" minHeight="9.0" prefHeight="12.0" vgrow="SOMETIMES" />
        <RowConstraints maxHeight="481.0" minHeight="10.0" prefHeight="478.0" vgrow="SOMETIMES" />
    </rowConstraints>
    <children>
        <Button fx:id="start" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#startOnAction" prefHeight="220.0" prefWidth="578.0" text="Start Recording" />
        <TextArea fx:id="console" editable="false" prefHeight="200.0" prefWidth="200.0" promptText="Console" wrapText="true" GridPane.rowIndex="2" />
        <TextField fx:id="input" prefHeight="105.0" prefWidth="578.0" promptText="File Name" GridPane.rowIndex="1" />
    </children>
</GridPane>

FXMLDocumentController (Where the snip of code was from):

package recorder;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javax.imageio.ImageIO;
import javax.media.MediaLocator;
import javax.swing.JOptionPane;

public class FXMLDocumentController implements Initializable {

    File file;
    /**
     * Screen Width.
     */
    public static int screenWidth = (int) Toolkit.getDefaultToolkit()
            .getScreenSize().getWidth();

    /**
     * Screen Height.
     */
    public static int screenHeight = (int) Toolkit.getDefaultToolkit()
            .getScreenSize().getHeight();

    /**
     * Interval between which the image needs to be captured.
     */
    public static int captureInterval = 50;

    /**
     * Temporary folder to store the screenshot.
     */
    public static String store = "tmp";

    /**
     * Status of the recorder.
     */
    public static boolean record = false;

    @FXML
    private Button start;

    @FXML
    private TextArea console;

    @FXML
    private TextField input;

    public static void startRecord() {
        Thread recordThread = new Thread() {
            @Override
            public void run() {
                Robot rt;
                int cnt = 0;
                try {
                    rt = new Robot();
                    while (cnt == 0 || record) {
                        BufferedImage img = rt.createScreenCapture(new Rectangle(screenWidth, screenHeight));
                        ImageIO.write(img, "jpeg", new File("./" + store + "/"
                                + System.currentTimeMillis() + ".jpeg"));
                        if (cnt == 0) {
                            record = true;
                            cnt = 1;
                        }
                        Thread.sleep(captureInterval);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        recordThread.start();
    }

    /**
     * @throws MalformedURLException
     *
     */
    public static void makeVideo(String movFile) throws MalformedURLException {
        FXMLDocumentController FXML = new FXMLDocumentController();
        FXML.console.appendText("Processing Video... please wait");
        JpegImagesToMovie imageToMovie = new JpegImagesToMovie();
        Vector<String> imgLst = new Vector<String>();
        File f = new File(store);
        File[] fileLst = f.listFiles();
        for (int i = 0; i < fileLst.length; i++) {
            imgLst.add(fileLst[i].getAbsolutePath());
        }
        // Generate the output media locators.
        MediaLocator oml;
        if ((oml = imageToMovie.createMediaLocator(movFile)) == null) {
            FXML.console.appendText("Error in processing");
            System.exit(0);
        }
        imageToMovie.doIt(screenWidth, screenHeight, (1000 / captureInterval), imgLst, oml);

    }

    @FXML
    void setOnAction(ActionEvent event) {
        String path = JOptionPane.showInputDialog("Type in the File Path", "C:/Users/" + System.getProperty("user.name") + "/Desktop");
        file = new File(path);
    }

    @FXML
    void startOnAction(ActionEvent event) {
        FXMLDocumentController FXML = new FXMLDocumentController();
        FXML.console.setText("######### Starting Screen Recorder #########");
        try {
            Thread.sleep(250);
        } catch (InterruptedException  ex) {
        }
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        FXML.console.appendText("Your Screen [Width, Height]: " + "[" + screen.getWidth() + "," + screen.getHeight() + "]\nWhen the Recording starts, this window will minimize, to stop them recording, open this window.");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
        }
        FXML.console.appendText("The recording will start in 5 seconds");
        int num = 5;
        for (int i = 0; i <= 5; i++) {
            System.out.print(num);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
            }
            num = num - 1;
        }
        FXML.console.appendText("Start!");
        File f = new File(store);
        if (!f.exists()) {
            f.mkdir();
        }
        startRecord();
        Recorder R = new Recorder();
        R.stage.setIconified(true);
        R.stage.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
            focusState(newValue);
        });
    }

    ;

    private void focusState(boolean value) {
        if (value) {
            System.out.println("Focus Gained");
            record = false;
            try {
                makeVideo(input.getText() + ".mov");
            } catch (MalformedURLException ex) {
            }
        } else {
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {

    }

}

I hope I correctly followed your guidelines and stuff.

Upvotes: 4

Views: 351

Answers (1)

fabian
fabian

Reputation: 82461

You're just creating an instance of FXMLDocumentController that has no connection to any fxml that has been loaded with a FXMLLoader.

However it's the FXMLLoader that's responsible for injecting field values and it does only inject the fields to instances of the controller class used with the FXMLLoader when the fxml file is loaded (I.e. either one created by the FXMLLoader itself based on the fx:controller attribute or one provided using setController; in both cases the instance can be retrieved using FXMLLoader.getController directly after calling load).

Fields that are never modified still contain the default value null, which causes the NPE e.g. here:

FXMLDocumentController FXML = new FXMLDocumentController();
FXML.console.setText("######### Starting Screen Recorder #########");

this.console.setText("######### Starting Screen Recorder #########");

would probably succeed, but note that you are blocking the application thread in your code with Thread.sleep for several seconds, which will make the application freeze for this time...


To retrieve the Window after a scene has been added to it, you can use a Node inside the scene instead:

Stage stage = (Stage) this.console.getScene().getWindow();
stage.setIconified(true);
stage.focusedProperty()...

Upvotes: 1

Related Questions