javavideojavafxjframejava-canvas

How can I possibly draw a JavaFX video in a JFrame's canvas?


Basically, I want to "add" a JavaFX video to a Java Swing JFrame, but I also want to draw in that canvas, to do other things while playing the video. I use this code to play the video:

    public class ExtVideoPlayer extends Application implements dev.ckitty.kc.utils.interf.MediaPlayer {

    @Override
    public MediaPlayerType[] getAcceptedTypes() {
        return new MediaPlayerType[] { MediaPlayerType.VIDEO };
    }

    @Override
    public void init(File f, String s) {

    }

    @Override
    public void start() {
        ExtVideoPlayer.launch(new String[0]);
    }

    @Override
    public void command(String[] args) {

    }

    @Override
    public void stop() {

    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        StackPane root = new StackPane();

        File video = new File("C:\\Users\\980001005\\Videos\\IMG_6503.mp4");
        String url = video.toURI().toURL().toString();
        Media media = new Media(url);
        MediaPlayer player = new MediaPlayer(media);
        MediaView mediaView = new MediaView(player);

        root.getChildren().add(mediaView);
        Scene scene = new Scene(root, mediaView.getFitWidth(), mediaView.getFitHeight());

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

        player.play();
    }

}

This works fine, but creates other windows! Of course I could just make it pop-out videos but that would look awful.

I want it to look like Youtube, for example. People would be able to vote for a video and the votes would be shown where Youtube shows recommended videos and adds.

There are some tricks I've seen to put the video inside the JFrame as a Component, but I want it to have a Canvas I can use as well. (So I can draw over the playing video or something)

Please Help!

EDIT! This answer seems like the one I have to use.

EDIT 2

Now I got the canvas and the video in the same JFrame, however, the canvas is not transparent!

The code

   public class LayeredDisplay extends Display {

    protected JLayeredPane pane;
    protected JPanel ontop, behind;
    protected JFXPanel jfxPanel;

    public LayeredDisplay(String title, int w, int h) {
        super(title, w, h, false);
        this.createLayers();
        this.frame.pack();
        this.frame.requestFocus();
        this.frame.setSize(w, h);
        this.frame.setVisible(true);
    }

    protected void createLayers() {

        this.jfxPanel = new JFXPanel();
        this.canvas = new Canvas();

        Dimension dim = new Dimension(this.w, this.h);

        this.canvas.setPreferredSize(dim);
        this.canvas.setMaximumSize(dim);
        this.canvas.setMinimumSize(dim);
        this.canvas.setFocusable(false);

        //this.ontop.add(this.canvas);

        //pane.add(this.ontop, 2);
        //pane.add(this.behind, 1);

        this.frame.add(this.jfxPanel, 0);
        this.frame.add(canvas, 1);
    }

    public JLayeredPane getPane() {
        return this.pane;
    }

    public JPanel getFront() {
        return this.ontop;
    }

    public JPanel getBack() {
        return this.behind;
    }

    public void addComponent(Component comp) {
        this.behind.add(comp);
    }

    public void addVideo(File video1) {
        Util.initJavaFX();

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Code to change Swing data.

                File video = new File("C:\\Users\\980001005\\Videos\\IMG_6503.mp4");
                String url = null;

                try {
                    url = video.toURI().toURL().toString();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }

                Media media = new Media(url);
                MediaPlayer player = new MediaPlayer(media);
                MediaView view = new MediaView(player);

                player.play();
                jfxPanel.setScene(new Scene(new Group(view)));
            }
        });

    }

}

The Display class I'm extending holds the canvas and the JFrame and gives me the Graphics object to draw in the canvas, nothing special.


Solution

  • I got the result I needed! I put the JFXPanel in a class to manage the video. You basically need to add the JFXPanel into a JPanel

    public class FramePlayer {
    
        private Display disp;
        private JFXPanel jfxPanel;
        private int w, h;
    
        public FramePlayer(Display disp, int w, int h, boolean autoInit) {
            this.disp = disp;
            this.w = w;
            this.h = h;
            if(autoInit) this.init();
        }
    
        public void init() {
            this.jfxPanel = new JFXPanel();
    
            Dimension dim = new Dimension(w, h);
            this.jfxPanel.setPreferredSize(dim);
            this.jfxPanel.setBackground(new Color(0, 0, 0, 255));
            this.jfxPanel.setOpaque(false);
    
            this.disp.getFrame().add(this.jfxPanel, 1);
        }
    
        public void addVideo(File video1) {
            Util.initJavaFX();
    
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    // Code to change Swing data.
    
                    File video = new File("C:\\Users\\980001005\\Videos\\IMG_6503.mp4");
                    String url = null;
    
                    try {
                        url = video.toURI().toURL().toString();
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
    
                    Media media = new Media(url);
                    MediaPlayer player = new MediaPlayer(media);
                    MediaView view = new MediaView(player);
    
                    Group g = new Group(view);
                    Scene s = new Scene(g);
                    s.setFill(Paint.valueOf("TRANSPARENT")); // THIS MAKES IT TRANSPARENT!
    
                    player.play();
                    jfxPanel.setScene(s);
                }
            });
        }
    
        public void renderVideo() {
            this.jfxPanel.paint(this.disp.getGfx().get());
        }
    
        public void renderVideo(KCGraphics gfx) {
            this.jfxPanel.paint(gfx.get());
        }
    
    }
    

    You need to 1. add the JFXPanel to the JPanel 2. force drawing the JFXPanel into the canvas (well, that's what I had to do..) 3. enjoy!