1

I have just started with JavaFX. I'm in the process of developing a GUI for my program, and I've used SceneBuilder to design my GUI. I currently have a main class that uses an FXMLLoader to load an .fxml file and displays it. This FXML file has another class called "Controller" as controller. As I said, I haven't had that much to do with JavaFX, so it's possible that I'm just doing it wrong.

Now I have 2 problems: First, I want to communicate between the two classes (code follows). Second, I would like to know how to integrate the code from the main class of the GUI into my already existing main class, I already tried it, but I always got only error messages (stacktrace and code follows).

isi_ko

My GUI Main Class

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

public class Main  extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent normalParent = FXMLLoader.load(getClass().getResource("normalLayout.fxml"));

        primaryStage.setTitle("Test");
        primaryStage.setScene(new Scene(normalParent, primaryStage.getWidth(), primaryStage.getHeight()));
        primaryStage.show();
    }
}

My GUI Controller Class

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Stage;

public class Controller implements EventHandler<ActionEvent> {

    @FXML Label activePercent;
    @FXML Label activeLabel;
    @FXML Label activeNumber;

    @FXML Label lastLable;
    @FXML Label lastNumber;

    @FXML Label nextLabel;
    @FXML Label nextNumber;

    @FXML Label faderValue1;
    @FXML Label faderValue2;
    @FXML Label faderValue3;
    @FXML Label faderValue4;
    @FXML Label faderValue5;

    @FXML
    public void test() {
    }

    @Override
    public void handle(ActionEvent event) {
        getFaderValueLable(1).setText("1");
        getFaderValueLable(2).setText("2");
        getFaderValueLable(3).setText("3");
        getFaderValueLable(4).setText("4");
        getFaderValueLable(5).setText("5");
    }

    public Label getFaderValueLable(int i){
        switch (i){
            case 1:
                return faderValue1;
            case 2:
                return faderValue2;
            case 3:
                return faderValue3;
            case 4:
                return faderValue4;
            case 5:
                return faderValue5;
            default:
                return null;
        }
    }
}

My normal Main Class (without GUI Code)

import com.fazecast.jSerialComm.SerialPort;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;

public class Main{

    Fader[] faders;
    final int baudRate = 1000000;                   //The Speed that is Used to Communicate with the Arduino
    private int physicalFaderAmount;                        //Amount of Physical Faders, counted from 1
    private int faderPages;                         //Amount of Faderpages, counted from 1
    private int activeFaderpage;                    //The Currently active "physical" Faderpage
    private ArduinoController arduinoController;    //The Class that communicates with the Arduino

    private EosOscController oscController;         //The Class that Communicates with Eos

    Main(String[] args) {
        //Todo Redo this part when UI done
        //at the Moment here are just some default values

        activeFaderpage = 0;
        physicalFaderAmount = 5;
        faderPages = 4;

        faders = new Fader[physicalFaderAmount];
        for (int i = 0; i < physicalFaderAmount; i++){
            faders[i] = new Fader(faderPages, i);
        }

        oscController = new EosOscController(8001, 8000, "192.168.178.133", this);
        arduinoController = new ArduinoController(SerialPort.getCommPort("COM4"), this);
    }

    public static void main(String[] args) {
        Main main = new Main(args);
    }

    //  This Class is for Storing Information about a particular physical Fader
    public class Fader {

        public int[][] values;
//        The last 3 Falues the Fader has on the Different Faderpages.
//        The First Koordinate is for the Page, the second coordinate is for which of the last 3 Values you want to use.
//        The First Value of Every page is the Current value of the Fader
//        The Others are for detecting inconsistent Potivalues

        public int faderID;         //The number of the Physical Fader, starting from 0.

//      Uses local values, not OSC
//      Sets the Value of the Fader
//      Can send the new Value directly to the Arduino or Eos
        public void setValue(int physicalPage, int value, boolean sendToEos, boolean sendToArduino) {
            if (value != this.values[physicalPage][2] || (Math.max(values[physicalPage][1], value) - Math.min(values[physicalPage][1], value)) > 1) {
                values[physicalPage][0] = value;

                //Todo: Test this
                if (sendToEos) {

                    oscController.setFaderIntensity(physicalPage, faderID, value / 100.0D, true);
                }

                //Todo Test this
                if (sendToArduino) {
                    arduinoController.sendMessage(new ArduinoController.MessageToArduino(faderID, value), true);
                }
            }

            values[physicalPage][2] = values[physicalPage][1];
            values[physicalPage][1] = value;
        }

        Fader(int pages, int faderID) {
            values = new int[pages][3];
            this.faderID = faderID;
        }

    }
}

My normal Main Class (with GUI Code)

import com.fazecast.jSerialComm.SerialPort;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application{

    Fader[] faders;
    final int baudRate = 1000000;                   //The Speed that is Used to Communicate with the Arduino
    private int physicalFaderAmount;                        //Amount of Physical Faders, counted from 1
    private int faderPages;                         //Amount of Faderpages, counted from 1
    private int activeFaderpage;                    //The Currently active "physical" Faderpage
    private ArduinoController arduinoController;    //The Class that communicates with the Arduino

    private EosOscController oscController;         //The Class that Communicates with Eos

    Main() {
        //Todo Redo this part when UI done
        //at the Moment here are just some default values

        activeFaderpage = 0;
        physicalFaderAmount = 5;
        faderPages = 4;

        faders = new Fader[physicalFaderAmount];
        for (int i = 0; i < physicalFaderAmount; i++){
            faders[i] = new Fader(faderPages, i);
        }

        oscController = new EosOscController(8001, 8000, "192.168.178.133", this);
        arduinoController = new ArduinoController(SerialPort.getCommPort("COM4"), this);    // For PC
//        arduinoController = new ArduinoController(SerialPort.getCommPort("ttyACM0"), this); //For Raspberry Pi
    }

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent normalParent = FXMLLoader.load(getClass().getResource("normalLayout.fxml"));

        primaryStage.setTitle("Test");
        primaryStage.setScene(new Scene(normalParent, primaryStage.getWidth(), primaryStage.getHeight()));
        primaryStage.show();
    }

    //  This Class is for Storing Information about a particular physical Fader
    public class Fader {

        public int[][] values;
//        The last 3 Falues the Fader has on the Different Faderpages.
//        The First Koordinate is for the Page, the second coordinate is for which of the last 3 Values you want to use.
//        The First Value of Every page is the Current value of the Fader
//        The Others are for detecting inconsistant Potivalues

        public int faderID;         //The number of the Physical Fader, starting from 0.

//      Uses local values, not OSC
//      Sets the Value of the Fader
//      Can send the new Value directly to the Arduino or Eos
        public void setValue(int physicalPage, int value, boolean sendToEos, boolean sendToArduino) {
            if (value != this.values[physicalPage][2] || (Math.max(values[physicalPage][1], value) - Math.min(values[physicalPage][1], value)) > 1) {
                values[physicalPage][0] = value;

                //Todo: Test this
                if (sendToEos) {

                    oscController.setFaderIntensity(physicalPage, faderID, value / 100.0D, true);
                }

                //Todo Test this
                if (sendToArduino) {
                    arduinoController.sendMessage(new ArduinoController.MessageToArduino(faderID, value), true);
                }
            }

            values[physicalPage][2] = values[physicalPage][1];
            values[physicalPage][1] = value;
        }

        Fader(int pages, int faderID) {
            values = new int[pages][3];
            this.faderID = faderID;
        }

    }
}

Stacktrace for Main Class with GUI Code

Exception in Application constructor
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 com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    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.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Unable to construct Application instance: class Main
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoSuchMethodException: Main.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getConstructor(Class.java:1825)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$7(LauncherImpl.java:818)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$3(WinApplication.java:177)
    ... 1 more
Exception running application Main

Process finished with exit code 1
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
isi_ko
  • 417
  • 1
  • 5
  • 14
  • 2
    The error is simply because you don't have a no-arg constructor in `Main`. Just remove the parameter to the constructor (you're not using it), and remove `Main main =new Main(args)` from `main(...)` (it won't get called until after the GUI exits, and `launch()` instantiates `Main` anyway). If I understand the rest of the question correctly, just pass `this` (or `faders`, or whatever it is you need) to the controller (see https://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml) – James_D May 11 '20 at 13:11
  • I updated my code, but got the same Error Messag. Hope I did what you told me to, if not, it would be nice if you would explain it a bit more. – isi_ko May 11 '20 at 15:35
  • 2
    Oh, the constructor also needs to be `public`. – James_D May 11 '20 at 15:36
  • Thanks now that works. I'll maby write again later if I have a problem with the Second part :D – isi_ko May 11 '20 at 15:38

0 Answers0