如何将Javafx(非fxml)分离到fxml和控制器? (调用目标例外)

时间:2015-12-22 04:39:02

标签: java opencv javafx javafx-8

我正在构建一个可以显示网络摄像头实时反馈的应用程序。所以我一直在搜索示例代码,因为JavaFX中没有网络摄像头支持,最后我找到了代码(javaFX + OpenCV)。 但我正在为我的应用程序使用fxml,我找到的示例代码是Non-Fxml。

以下代码是示例代码,我无法将其分解为FXML及其控制器 从这里我找到两种方法 1:打破非fxml代码 2:在我的应用程序中使用非fxml示例代码。那么可以将非FXML java代码与FXML应用程序一起使用吗? 或者还有其他方式吗?

对于那些在javaFX中需要网络摄像头支持的人来说,这个代码段工作得很好。唯一的要求是OPENCV库。 虽然我不能赞成代码。 提前谢谢

package test;

import java.io.ByteArrayInputStream;

import javafx.animation.AnimationTimer; 
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.videoio.VideoCapture;

public class Camera2 extends Application {

public static void main(String[] args) {
    launch(args);
}
private static final int SCENE_W = 640;
private static final int SCENE_H = 480;


VideoCapture videoCapture;

Canvas canvas;
GraphicsContext g2d;
Stage stage;
AnimationTimer timer;

@Override
public void start(Stage stage) {

    this.stage = stage;

    initOpenCv();

    canvas = new Canvas(SCENE_W, SCENE_H);
    g2d = canvas.getGraphicsContext2D();
    g2d.setStroke(Color.GREEN);

    Group group = new Group(canvas);

    Scene scene = new Scene(group, SCENE_W, SCENE_H);

    stage.setScene(scene);
    stage.setResizable(false);
    stage.show();

    timer = new AnimationTimer() {

        Mat mat = new Mat();

        @Override
        public void handle(long now) {

            videoCapture.read(mat);

            Image image = mat2Image(mat);

            g2d.drawImage(image, 0, 0);

        }
    };
    timer.start();

}

private void initOpenCv() {

    //setLibraryPath();
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

    videoCapture = new VideoCapture();
    videoCapture.open(0);

    System.out.println("Camera open: " + videoCapture.isOpened());

    stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
        public void handle(WindowEvent we) {

            timer.stop();
            videoCapture.release();

            System.out.println("Camera released");

        }
    });

}

public static Image mat2Image(Mat mat) {
    MatOfByte buffer = new MatOfByte();
    Imgcodecs.imencode(".png", mat, buffer);
    return new Image(new ByteArrayInputStream(buffer.toArray()));
}

}

我尝试在mycontroller文件中使用上面的代码

public class FXMLDocumentController implements Initializable {

@FXML
private Canvas canvas;

@FXML
private Button button_start;
private static final int SCENE_W = 640;
private static final int SCENE_H = 480;

VideoCapture videoCapture;
GraphicsContext g2d;
Stage stage;
AnimationTimer timer;


@FXML
private void handleButtonAction(ActionEvent event) {

}

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

    //   this.stage = stage;
    initOpenCv();

    canvas = new Canvas(SCENE_W, SCENE_H);
    g2d = canvas.getGraphicsContext2D();
    g2d.setStroke(Color.GREEN);

    Group group = new Group(canvas);

    Scene scene = new Scene(group, SCENE_W, SCENE_H);

    stage.setScene(scene);
    stage.setResizable(false);
    stage.show();

    timer = new AnimationTimer() {

        Mat mat = new Mat();

        @Override
        public void handle(long now) {

            videoCapture.read(mat);

            Image image = mat2Image(mat);

            g2d.drawImage(image, 0, 0);

        }
    };
    timer.start();

}

private void initOpenCv() {

    //setLibraryPath();
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

    videoCapture = new VideoCapture();
    videoCapture.open(0);

    System.out.println("Camera open: " + videoCapture.isOpened());

    stage.setOnCloseRequest((WindowEvent we) -> {
        timer.stop();
        videoCapture.release();

        System.out.println("Camera released");
    });

}

但我收到以下错误

Exception in Application start method
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: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: 
file:/home/anurag/NetBeansProjects/Test2/dist/run1986258874/Test2.jar!/test2/FXMLDocument.fxml

at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
at test2.Test2.start(Test2.java:22)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
... 1 more
Caused by: java.lang.NullPointerException
at test2.FXMLDocumentController.initOpenCv(FXMLDocumentController.java:104)
at test2.FXMLDocumentController.initialize(FXMLDocumentController.java:61)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
... 17 more
Exception running application test2.Test2

1 个答案:

答案 0 :(得分:1)

我不确定你到底想要什么,但我想你可以调整你暴露的代码,因为它只是一个带有画布的组。 例如:

groupwithcanvas.fxml

<?import javafx.scene.Group?>
<?import javafx.scene.canvas.Canvas?>

<Group xmlns:fx="http://javafx.com/fxml/1" fx:controller="GroupWithCanvasController">
    <Canvas fx:id="myCanvas"></Canvas>
</Group>

GroupWithCanvasController.java

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;

import java.net.URL;
import java.util.ResourceBundle;

public class GroupWithCanvasController implements Initializable {


    @FXML
    private Canvas myCanvas;


    @Override
    public void initialize(URL location, ResourceBundle resources) {

        // DO STUFFS

    }
}

MainApp.java

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


public class MainApp extends Application {


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

        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(MainApp.class.getClassLoader().getResource("groupwithcanvas.fxml"));
        Group group = loader.load();
        Scene scene = new Scene(group);
        primaryStage.setScene(scene);
        primaryStage.show();

    }


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

您必须调整initialize()中的所有OpenCV逻辑,但这应该是可行的。