This discussion is archived
3 Replies Latest reply: Feb 27, 2013 10:48 AM by James_D RSS

Unsynchronized threads when adding looping video to JPanel

993750 Newbie
Currently Being Moderated
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);

Platform.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();
}
}

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 then it craps out. So I tried creating an ArrayList of Group objects and creating 100 of them and passing in the next one for every loop, 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 got a feeling that javafx.concurrent is the way to go, but I can't figure out how to implement it in my code. I've been working on this for 2 days straight, to no avail, and would really appreciate it if someone could point me in the right direction. Thanks.
  • 1. Re: Unsynchronized threads when adding looping video to JPanel
    James_D Guru
    Currently Being Moderated
    It looks like you're making this considerably more complex than it needs to be (which happens when you're a new programmer).

    First, do you need to use Swing? Embedding JavaFX in Swing is tricky and creates complex threading issues you need to manage in a relatively low-level way. Unless there are other requirements you've not mentioned, you should be able to do this all in JavaFX. The [url http://docs.oracle.com/javafx/2/get_started/hello_world.htm]Hello World example gives a simple example; then look at the [url http://docs.oracle.com/javafx/2/layout/jfxpub-layout.htm]layout tutorial to see how to do some simple layouts.

    To create a looping video, you don't need to restart it by hand, as you're trying to do with the listener for the end of media. Just use
    player.setCycleCount(MediaPlayer.INDEFINITE);
    and it will loop indefinitely. You can still respond to it restarting (if you want to do something else, like change the image) by registering a change listener with the mediaPlayer's currentCount property.
  • 2. Re: Unsynchronized threads when adding looping video to JPanel
    993750 Newbie
    Currently Being Moderated
    I cannot thank you enough for this. It works! And to think it all came down to a single, simple line of code.

    Unfortunately yes, I have to use Swing, since that's what this class is about. I have one follow-up question, however. Now that looping works, the MouseListener I put on it doesn't. Any idea why?
  • 3. Re: Unsynchronized threads when adding looping video to JPanel
    James_D Guru
    Currently Being Moderated
    Hard to know since your code sample doesn't show the mouse listener.

    Post a new question (i.e. a new forum thread) to get help with that, and include enough code to show the mouse listener registration, etc. (It helps if you format your code, too, by placing it in {noformat}
    ...
    {noformat} tags.)

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points