TheShahin
TheShahin

Reputation: 153

Threads while looping video to JPanel using JavaFX

I'm working on a project for school at the moment where I'm trying to create an image gallery and video player. In the welcome-window I've created two JPanels with MouseListeners, one to hold an image and one to hold a looping video of approximately 5 seconds. At first I used this:

public class WelcomeVideoLoader extends JPanel implements Runnable {

Media media;
MediaPlayer player;
MediaView view;
JFXPanel jfxPanel;
Dimension d;
DoubleProperty width;
DoubleProperty height;
Group root;

public WelcomeVideoLoader(File file, Dimension d) {

    this.d = d;
    media = new Media(file.toURI().toString());

    jfxPanel = new JFXPanel();

    playAndLoopVideo();

}

private void playAndLoopVideo() {

    root = new Group();

    player = new MediaPlayer(media);
    player.play();
    player.setMute(true);
    view = new MediaView(player);

    DoubleProperty width = view.fitWidthProperty();
    DoubleProperty height = view.fitHeightProperty();

    width.bind(Bindings.selectDouble(view.sceneProperty(), "width"));
    height.bind(Bindings.selectDouble(view.sceneProperty(), "height"));

    view.setPreserveRatio(true);
    root.getChildren().add(view);
    player.setOnEndOfMedia(this);

    PlatformImpl.runLater(
            new Runnable() {
                @Override
                public void run() {
                    Scene scene = new Scene(root, d.getWidth(), d.getHeight());
                    jfxPanel.setScene(scene);
                }
            });

    super.add(jfxPanel);
}

@Override
public void run() {
    player.stop();
    playAndLoopVideo();
}
}

And this is the stacktrace:

Exception in runnable
java.lang.IllegalArgumentException: Group@4d714a77[styleClass=root]is already set as root     of another scene
at javafx.scene.Scene$10.invalidated(Scene.java:991)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:129)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:163)
at javafx.scene.Scene.setRoot(Scene.java:953)
at javafx.scene.Scene.<init>(Scene.java:291)
at javafx.scene.Scene.<init>(Scene.java:260)
at se.theshahin.gallery.utils.WelcomeVideoLoader$1.run(WelcomeVideoLoader.java:69)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javafx.embed.swing.JFXPanel$HostContainer$1.run(JFXPanel.java:741)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:688)
at java.awt.EventQueue$3.run(EventQueue.java:686)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

This works for maybe 6-7 loops, but I get an IllegalArgumentException for every loop, saying that Group was already used in another Scene. So I tried creating an ArrayList of Group objects and creating 100 of them, to see if that worked. It didn't. It turns out that my Threads are working independently from one another and after a while they get muddled up.

I'm still new to programming and can't seem to find much on the topic that I can understand, everything seems to be written for people with years of experience. I've been working on this for 16 hours straight, to no avail, and would really appreciate it if someone could point me in the right direction. Thanks.

Upvotes: 0

Views: 1044

Answers (1)

javajon
javajon

Reputation: 1698

For those of you who are on occasion receiving this exception as noted above:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javafx.embed.swing.JFXPanel$HostContainer$1.run(JFXPanel.java:741)...

This happens in Java 7, but not in Java 8. What propagates the error seems to vary.

The source of error is in JFXPanel.java. In Java 8 JFXPanel.java was changed to add a null pointer check:

if (scenePeer != null)

The Java 7 decompiled version (open source not available) looks like this:

   public void setEmbeddedScene(EmbeddedSceneInterface var1) {
        JFXPanel.this.scenePeer = var1;
        if(JFXPanel.this.scenePeer != null) {
            if(JFXPanel.this.pWidth > 0 && JFXPanel.this.pHeight > 0) {
                JFXPanel.this.scenePeer.setSize(JFXPanel.this.pWidth, JFXPanel.this.pHeight);
            }

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFXPanel.this.scenePeer.setDragStartListener(JFXPanel.this.dnd.getDragStartListener());
                }
            });
        }
    }

The JFXPanel class in Java 8 was fixed with the extra null check

public void setEmbeddedScene(EmbeddedSceneInterface embeddedScene) {
    scenePeer = embeddedScene;
    if (scenePeer == null) {
        return;
    }
    if (pWidth > 0 && pHeight > 0) {
        scenePeer.setSize(pWidth, pHeight);
    }

    // DnD-related calls on 'scenePeer' should go from AWT EDT.
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            if (scenePeer != null) {
                scenePeer.setDragStartListener(dnd.getDragStartListener());
            }
        }
    });
}

Upvotes: 2

Related Questions