更改 JavaFX 应用程序启动表单

Change JavaFX Application Start Form

我当前的项目是一个带有 RMI 的 JavaFX 应用程序。目前我有两个三个 classes,我想减少到两个,但我无法找到如何。

三个class: StartClient.java BannerController.java AEXBanner.java

代码和错误消息:

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:497) 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:497) at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767) Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = main at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:236) at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423) at javafx.stage.Stage.(Stage.java:241) at javafx.stage.Stage.(Stage.java:227) at client.BannerController.(BannerController.java:71) at client.BannerController.main(BannerController.java:174) ... 11 more Exception running application client.BannerController D:\Dropbox\HBO ICT\Leerjaar 2\GSO3\AEXBanner Week 1\nbproject\build-impl.xml:1051: The following error occurred while executing this line: D:\Dropbox\HBO ICT\Leerjaar 2\GSO3\AEXBanner Week 1\nbproject\build-impl.xml:805: Java returned: 1 BUILD FAILED (total time: 17 seconds)

使用 StartClient 启动程序(而 RMI 服务器是 运行)一切正常。但是当我直接用 BannerController class 启动应用程序时,Netbeans 给我上面的错误。

我 100% 确定 RMI 服务器工作正常,因此无需担心。

三个 classes 可以在下面找到:

启动客户端:

package client;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 *
 * @author Max
 */
public class StartClient extends Application {

    @Override
    public void start(Stage primaryStage) {
        BannerController.main(null);
    }

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

横幅控制器: 打包客户端;

/**
 *
 * @author Max
 */
import shared.IEffectenBeurs;
import shared.IFonds;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.stage.Stage;

public class BannerController extends Application {

    private AEXBanner banner;
    private IEffectenBeurs effectenbeurs;
    private Timer pollingTimer;
    private String bindingName = "Effectenbeurs";
    private Registry registry = null;
    private static boolean locateRegistry = true;

    public BannerController(String ip, int port) {
        banner = new AEXBanner();
        pollingTimer = new Timer();

        System.out.println("Client: IP Address: " + ip);
        System.out.println("Client: Port number " + port);

        if (locateRegistry) {
            // Locate registry at IP address and port number
            registry = locateRegistry(ip, port);

            // Print result locating registry
            if (registry != null) {
                printContentsRegistry();
                System.out.println("Client: Registry located");
            } else {
                System.out.println("Client: Cannot locate registry");
                System.out.println("Client: Registry is null pointer");
            }
            if (registry != null) {
                effectenbeurs = bindEffectenbeursUsingRegistry();
            }
        } else {
            // Bind fonds using Naming
            effectenbeurs = bindEffectenbeursUsingNaming(ip, port);
        }
        if (effectenbeurs != null) {
            System.out.println("Client: Effectenbeurs bound");
        } else {
            System.out.println("Client: Effectenbeurs is null pointer");
        }
        banner.start(new Stage());
        pollingTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    StringBuilder sb = new StringBuilder();
                    for (IFonds f : effectenbeurs.getKoersen()) {
                        sb.append(f.toString() + " ");
                    }
                    System.out.println(sb.toString());
                    banner.setKoersen(sb.toString());
                } catch (RemoteException ex) {
                    Logger.getLogger(BannerController.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        }, 0, 2000);

    }

    // Print contents of registry
    private void printContentsRegistry() {
        try {
            String[] listOfNames = registry.list();
            System.out.println("Client: list of names bound in registry:");
            if (listOfNames.length != 0) {
                for (String s : registry.list()) {
                    System.out.println(s);
                }
            } else {
                System.out.println("Client: list of names bound in registry is empty");
            }
        } catch (RemoteException ex) {
            System.out.println("Client: Cannot show list of names bound in registry");
            System.out.println("Client: RemoteException: " + ex.getMessage());
        }
    }

    private IEffectenBeurs bindEffectenbeursUsingRegistry() {
        IEffectenBeurs effectenbeurs1 = null;
        try {
            Object object = registry.lookup(bindingName);
            effectenbeurs1 = (IEffectenBeurs) registry.lookup(bindingName);
        } catch (RemoteException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: RemoteException: " + ex.getMessage());
            effectenbeurs1 = null;
        } catch (NotBoundException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: NotBoundException: " + ex.getMessage());
            effectenbeurs1 = null;
        }
        return effectenbeurs1;
    }

    private Registry locateRegistry(String ipAddress, int portNumber) {
        Registry registry = null;
        try {
            registry = LocateRegistry.getRegistry(ipAddress, portNumber);
        } catch (RemoteException ex) {
            System.out.println("Client: Cannot locate registry");
            System.out.println("Client: RemoteException: " + ex.getMessage());
            registry = null;
        }
        return registry;
    }

    private IEffectenBeurs bindEffectenbeursUsingNaming(String ipAddress, int portNumber) {
        IEffectenBeurs Effectenbeurs = null;
        try {
            Effectenbeurs = (IEffectenBeurs) Naming.lookup("rmi://" + ipAddress + ":" + portNumber + "/" + bindingName);
        } catch (MalformedURLException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: MalformedURLException: " + ex.getMessage());
            Effectenbeurs = null;
        } catch (RemoteException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: RemoteException: " + ex.getMessage());
            Effectenbeurs = null;
        } catch (NotBoundException ex) {
            System.out.println("Client: Cannot bind Effectenbeurs");
            System.out.println("Client: NotBoundException: " + ex.getMessage());
            Effectenbeurs = null;
        }
        return Effectenbeurs;
    }

    public static void main(String[] args) {
        if (locateRegistry) {
            System.out.println("CLIENT USING LOCATE REGISTRY");
        } else {
            System.out.println("CLIENT USING NAMING");
        }

//        // Get ip address of server
        Scanner input = new Scanner(System.in);
        System.out.print("Client: Enter IP address of server: ");
        String ipAddress = input.nextLine();

        // Get port number
        System.out.print("Client: Enter port number: ");
        int portNumber = input.nextInt();
        // Create client
        BannerController client = new BannerController(ipAddress, portNumber);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

    }
}

我非常怀疑第三个 class 与此问题有任何关系,但以防万一:我将其包括在内。

AEX 横幅: 打包客户端;

import java.rmi.RemoteException;
import javafx.animation.AnimationTimer;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class AEXBanner extends Application {

    public static final int WIDTH = 1000;
    public static final int HEIGHT = 100;
    public static final int NANO_TICKS = 20000000;
    // FRAME_RATE = 1000000000/NANO_TICKS = 50;

    private Text text;
    private double textLength;
    private double textPosition;
    private BannerController controller;

    private AnimationTimer animationTimer;
    private Timeline timeline;
    private int TIMERTICK = 200;
    private int frame = 0;
    private String koersen;

    public void setController(BannerController banner) {
        //controller = banner(this);
    }
    @Override
    public void start(Stage primaryStage) {

        Font font = new Font("Arial", HEIGHT);
        text = new Text();
        //controller = new BannerController(this);

        text.setFont(font);
        text.setFill(Color.BLACK);

        Pane root = new Pane();
        root.getChildren().add(text);
        Scene scene = new Scene(root, WIDTH, HEIGHT);

        primaryStage.setTitle("AEX banner");
        primaryStage.setScene(scene);
        primaryStage.show();
        primaryStage.toFront();

        timeline = new Timeline();
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.setAutoReverse(false);

        // Start animation: text moves from right to left
        animationTimer = new AnimationTimer() {
            private long prevUpdate;

            @Override
            public void handle(long now) {
                long lag = now - prevUpdate;
                if (lag >= NANO_TICKS) {
                    // calculate new location of text
                    // TODO
                    if (textPosition < 0 - textLength) {
                        textPosition = WIDTH;
                    }
                    textPosition -= 5;

                    text.relocate(textPosition, 0);
                    prevUpdate = now;
                }
            }

            @Override
            public void start() {
                prevUpdate = System.nanoTime();
                textPosition = WIDTH;
                text.relocate(textPosition, 0);
                //setKoersen("Nothing to display");
                super.start();
            }
        };
        animationTimer.start();
    }

    public void setKoersen(String koersen) {

        text.setText(koersen);

        textLength = text.getLayoutBounds().getWidth();
    }
}

所以总结一下我的问题(只是为了说清楚):当 RMI 服务器是 运行 时,我需要使用 StartClient 启动这个项目。 StartClient 启动 BannerController。我希望能够直接使用 BannerController class.

启动程序

任何提示或可能的解决方案将不胜感激!

编辑: 在 Lasagna 建议的 changeg 之后,当我启动 BannerController 时直接出现此错误:

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:497)
    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:497)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Unable to construct Application instance: class client.BannerController
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication5(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoSuchMethodException: client.BannerController.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getConstructor(Class.java:1825)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication11(LauncherImpl.java:818)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait5(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null3(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater4(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$null8(WinApplication.java:191)
    ... 1 more
Exception running application client.BannerController
D:\Dropbox\HBO ICT\Leerjaar 2\GSO3\AEXBanner Week 1\nbproject\build-impl.xml:1051: The following error occurred while executing this line:
D:\Dropbox\HBO ICT\Leerjaar 2\GSO3\AEXBanner Week 1\nbproject\build-impl.xml:805: Java returned: 1
BUILD FAILED (total time: 0 seconds)

让我们看看你的错误。

sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767) Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = main

这表示您没有 "FX Application Thread" 而您当前的主题是 "main."

这是因为您正尝试将 main 方法作为您的 "main method" 使用,但在 FX 中,它不是那样工作的(很奇怪吧?:))。 main 只是启动 FX 应用程序本身的一种方法,这就是您收到此错误的原因。


应用程序的启动方法是事情发生的地方。

在您的第一个 class "StartClient" 中,您使用 "BannerController" 的主程序,然后在您的主程序中使用“launch(args)”,这就是您启动 FX 应用程序的方式。

在您的横幅应用程序中,您有一个主要 class 和一堆东西,但没有 launch(args)

我也不确定为什么 "start" 会抛出一个没有代码的异常。


所以你需要做的是

  1. 从除主要 class 之外的所有 classes 中删除应用程序。
  2. 确保 main class 在 main 方法中有 "launch(args)"
  3. 确保主要 class 覆盖 "start" 方法,并且您 "launch" 从那里编写代码。

所以拿这个代码

public static void main(String[] args) {
        if (locateRegistry) {
            System.out.println("CLIENT USING LOCATE REGISTRY");
        } else {
            System.out.println("CLIENT USING NAMING");
        }

//        // Get ip address of server
        Scanner input = new Scanner(System.in);
        System.out.print("Client: Enter IP address of server: ");
        String ipAddress = input.nextLine();

        // Get port number
        System.out.print("Client: Enter port number: ");
        int portNumber = input.nextInt();
        // Create client
        BannerController client = new BannerController(ipAddress, portNumber);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

    }

并将其更改为

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

    @Override
    public void start(Stage primaryStage) throws Exception {
 if (locateRegistry) {
            System.out.println("CLIENT USING LOCATE REGISTRY");
        } else {
            System.out.println("CLIENT USING NAMING");
        }

//        // Get ip address of server
        Scanner input = new Scanner(System.in);
        System.out.print("Client: Enter IP address of server: ");
        String ipAddress = input.nextLine();

        // Get port number
        System.out.print("Client: Enter port number: ");
        int portNumber = input.nextInt();
        // Create client
        BannerController client = new BannerController(ipAddress, portNumber);
    }