同时运行javafx和swing应用程序 [英] Run javafx and swing application at the same time

查看:243
本文介绍了同时运行javafx和swing应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在java中使用Webcam Capture API来访问我的网络摄像头。 Webcam Capture API是基于Swing构建的,我知道,但是我想将Webcam Swing类与我的JavaFX类结合起来。 JavaFX类在屏幕上显示一个矩形。我的目标是:运行我的JavaFX类,在屏幕上显示矩形。在某些时候(例如鼠标点击)我想启动网络摄像头。网络摄像头设置为查看屏幕,然后应该使用矩形的图像做某些事情。

I'm using Webcam Capture API in java to access my webcam. Webcam Capture API is built on Swing, I know that, however I want to combine the Webcam Swing class with my JavaFX class. The JavaFX class displays a rectangle on the screen. My goal is: I run my JavaFX class which displays the rectangle on the screen. At some point (e.g. mouse click) I want to start the Webcam. The Webcam is setup to look at the screen and should then do certain things with the images of the rectangle.

JavaFX类:

public class JavaFXDisplay extends Application {

    @Override
    public void start(Stage primaryStage) {
        WebcamCapture wc = new WebcamCapture();

        StackPane root = new StackPane();

        Rectangle rectangle = new Rectangle();
        rectangle.setWidth(500);
        rectangle.setHeight(500);

        Scene scene = new Scene(root, 1000, 1000);
        root.getChildren().addAll(rectangle);

        primaryStage.setScene(scene);
        primaryStage.show();

        scene.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                wc.doSomething();
            }
        });
   }

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

Swing class:

Swing class:

public class WebcamCapture extends JFrame implements Runnable, ThreadFactory {

    private static final long serialVersionUID = 6441489157408381878L;

    private Executor executor = Executors.newSingleThreadExecutor(this);

    private Webcam webcam = null;
    private WebcamPanel panel = null;
    private JTextArea textarea = null;

    public WebcamCapture() {
        super();

        setLayout(new FlowLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Dimension size = WebcamResolution.QVGA.getSize();

        webcam = Webcam.getWebcams().get(0);
        webcam.setViewSize(size);

        panel = new WebcamPanel(webcam);
        panel.setPreferredSize(size);

        textarea = new JTextArea();
        textarea.setEditable(false);
        textarea.setPreferredSize(size);

        add(panel);
        add(textarea);

        pack();
        setVisible(true);
    }

    public void doSomething() {
        executor.execute(this);
    }

    @Override
    public void run() {
        do {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            BufferedImage image = null;

            if (webcam.isOpen()) {
                if ((image = webcam.getImage()) == null) {
                    continue;
                }

                doSomeStuff;
            }
        } while (true);
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, "example-runner");
        t.setDaemon(true);
        return t;
    }

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

但是我的JavaFX类没有启动/显示。我的代码有什么问题?

However my JavaFX class is not starting/displaying. What is wrong with my code?

推荐答案

我不熟悉您正在使用的网络摄像头API(所以我不喜欢不知道这是否是唯一的错误,但你确实需要在AWT事件派发线程上创建你的Swing内容。目前,您正在FX应用程序线程上创建它。

I'm not familiar with the web cam API you're using (so I don't know if this is the only thing wrong), but you do need to create your Swing content on the AWT event dispatch thread. Currently you are creating it on the FX Application Thread.

您可以使用以下习语:

public class JavaFXDisplay extends Application {

    private WebcamCapture wc ;

    @Override
    public void init() throws Exception {
        super.init();
        FutureTask<WebcamCapture> launchWebcam = new FutureTask<>(WebcamCapture::new) ;
        SwingUtilities.invokeLater(launchWebcam);

        // block until webcam is started:
        wc = launchWebcam.get();
    }

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

        StackPane root = new StackPane();

        Rectangle rectangle = new Rectangle();
        rectangle.setWidth(500);
        rectangle.setHeight(500);

        Scene scene = new Scene(root, 1000, 1000);
        root.getChildren().addAll(rectangle);

        primaryStage.setScene(scene);
        primaryStage.show();

        scene.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                wc.doSomething();
            }
        });
   }

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

作为参考,这里是一个仅限JavaFX的网络摄像头查看器。我在运行OS X Sierra(10.12.2)的MacBookPro上测试了这个,带有一个带有摄像头的2011年27Thunderbolt显示器。

For reference, here is a JavaFX-only webcam viewer. I tested this on a MacBookPro running OS X Sierra (10.12.2), with a 2011 27" Thunderbolt display with camera.

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamResolution;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class FXWebCamViewer extends Application {

    private BlockingQueue<Image> imageQueue = new ArrayBlockingQueue<>(5);

    private Executor exec = Executors.newCachedThreadPool(runnable -> {
        Thread t = new Thread(runnable);
        t.setDaemon(true);
        return t ;
    });

    private Webcam webcam;

    @Override
    public void init() {
        webcam = Webcam.getWebcams().get(0);
        Dimension viewSize = WebcamResolution.QVGA.getSize();
        webcam.setViewSize(viewSize);
        webcam.open();
    }

    @Override
    public void start(Stage primaryStage) {
        ImageView imageView = new ImageView();

        StackPane root = new StackPane(imageView);
        imageView.fitWidthProperty().bind(root.widthProperty());
        imageView.fitHeightProperty().bind(root.heightProperty());
        imageView.setPreserveRatio(true);

        AnimationTimer updateImage = new AnimationTimer() {
            @Override
            public void handle(long timestamp) {
                Image image = imageQueue.poll();
                if (image != null) {
                    imageView.setImage(image);
                }
            }
        };
        updateImage.start();

        exec.execute(this::generateImages);

        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void generateImages() {
        while (! Thread.interrupted()) {
            try {
                if (webcam.isOpen() && webcam.isImageNew()) {
                    BufferedImage bimg = webcam.getImage();
                    if (bimg != null) {
                        imageQueue.put(SwingFXUtils.toFXImage(bimg, null));
                    }
                } else {
                    Thread.sleep(250);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

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

这篇关于同时运行javafx和swing应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆