Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (804)
Games in Android Showcase (237)
games submitted by our members
Games in WIP (867)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [SOLVED] problem Adding/removing Nodes  (Read 38184 times)
0 Members and 1 Guest are viewing this topic.
Offline philfrei
« Posted 2017-01-02 01:23:42 »

[NOTE: Every time I have a question with JavaFX, I think I will post it here before searching elsewhere. If/when I find an answer, I will follow up and include it here, assuming no one beats me to it. Goal: JGO forums become more relevant to Java game programmers using JavaFX if we have more questions and tutorials at this site.]

I ran into the following error when trying to add or delete a Node from a method that is NOT the overridden start(Stage) method.
1  
    java.lang.IllegalStateException: Not on FX application thread; ... 


Example of calling code that elicits this error:
1  
    root.getChildren().add(img); 


For nodes added in the start() method, the code: root.getChildren().remove(img); creates the same error.

The code that tries to add or remove is located in a method in the same class that implements Application . A Group variable named root has been made an instance variable rather than the usual practice of making the root node a local variable of the start() method.

My goal is to manage cross-fades between different visual elements. I was thinking that once a node is faded out and no longer needed, I would delete it. And as new nodes are needed, I would add them. But the Exception is preventing this.

Alternatively, I can access the existing nodes to null them or vary their properties. Is this the way to manage the nodes? Flip the visibility or manage opacity and null them when they are not being used, but leave the nulled nodes as placeholders? That could leave me with a scene with 80% of the nodes being null or invisible at any one time which intuitively seems kind of fishy.

Or is this sort of thing (cross-fading lots of nodes) something that can or should be handled with managing multiple Scene variables?

music and music apps: http://adonax.com
Offline philfrei
« Reply #1 - Posted 2017-01-02 05:13:35 »

Found the answer!

The FX Application thread seems to be the JavaFX equivalent of the EDT on Swing. If this error crops up, the solution is to schedule the code to run on the FX Application thread. This can be done as follows:

1  
    Platform.runLater(Runnable runnable);


API for Platform

This being Java 8, the Runnable can be implemented via a Lambda, instead of an anonymous class.
1  
2  
3  
    Platform.runLater(
        () -> { root.getChildren().add(img); }
    );


The above reminds me of the code used in a main() when starting up an application that uses Swing:
1  
2  
3  
4  
5  
6  
7  
8  
    EventQueue.InvokeLater(new Runnable()
    {
        public void run()
        {
            JFrame frame = new JFrame();
            // etc.
        }
    });


As with the EDT, the API warns us not to try and do too much on the FX Application thread, as it can be a bottleneck.

music and music apps: http://adonax.com
Offline nsigma
« Reply #2 - Posted 2017-01-02 14:03:51 »

The FX Application thread seems to be the JavaFX equivalent of the EDT on Swing. If this error crops up, the solution is to schedule the code to run on the FX Application thread. This can be done as follows:

Surely you mean never, ever, ever touch JavaFX off the FX Application thread, the same as never, ever, ever touch Swing off the EDT?!  Pointing

Praxis LIVE - hybrid visual IDE for (live) creative coding
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline philfrei
« Reply #3 - Posted 2017-01-02 14:46:06 »

The FX Application thread seems to be the JavaFX equivalent of the EDT on Swing. If this error crops up, the solution is to schedule the code to run on the FX Application thread. This can be done as follows:

Surely you mean never, ever, ever touch JavaFX off the FX Application thread, the same as never, ever, ever touch Swing off the EDT?!  Pointing

I am still figuring out what is or isn't "touching" the FX Application thread, to use your terms.

There is a lot that can be done with JavaFX controls off of the FX thread. (And should be, to avoid clogging the thread and slowing down the app.) I can change properties from an external thread. In the opening for Hexara that I'm recoding, an animation thread is handling an opacity fade. The error message came up only when trying to add or remove a node to the current scene.

music and music apps: http://adonax.com
Offline nsigma
« Reply #4 - Posted 2017-01-02 14:55:28 »

I am still figuring out what is or isn't "touching" the FX Application thread, to use your terms.

There is a lot that can be done with JavaFX controls off of the FX thread. (And should be, to avoid clogging the thread and slowing down the app.) I can change properties from an external thread. In the opening for Hexara that I'm recoding, an animation thread is handling an opacity fade. The error message came up only when trying to add or remove a node to the current scene.

I didn't say touching the FX Application thread, I said touching JavaFX on another thread.  By which I mean pretty much anything!  Neither JavaFX or Swing are thread-safe, which means you should never create any object or call any method (of a JavaFX/Swing class) from anything other than the application thread / EDT unless it's specifically marked as thread-safe.  What you're doing may or may not work, for now, with this version of Java, with your OS, on your machine.

Praxis LIVE - hybrid visual IDE for (live) creative coding
Offline philfrei
« Reply #5 - Posted 2017-01-02 15:42:10 »

@nsigma Thanks for clarifying. I will keep your warning in mind.

Fingers crossed, maybe it's just a situation where property changes might not propagate in the order made or something minor, rather than an outright crash. I suspect that JavaFX is more robust than Swing. But I'll look into it further, and be on the lookout for problems as Hexara develops.

music and music apps: http://adonax.com
Offline nsigma
« Reply #6 - Posted 2017-01-02 16:18:09 »

Fingers crossed, maybe it's just a situation where property changes might not propagate in the order made or something minor, rather than an outright crash. I suspect that JavaFX is more robust than Swing.

Really don't assume that!  You're doing something the library is specifically designed not to support - robustness is therefore irrelevant.

From the Node JavaDoc -

Quote
Node objects may be constructed and modified on any thread as long they are not yet attached to a Scene. An application must attach nodes to a Scene, and modify nodes that are already attached to a Scene, on the JavaFX Application Thread.

Note this is different to Swing where you're not even supposed to construct or modify an unattached component off the EDT.

What you're doing looks like premature optimization, and one that probably isn't an optimization.  Wink

Praxis LIVE - hybrid visual IDE for (live) creative coding
Offline philfrei
« Reply #7 - Posted 2017-01-04 00:58:42 »

Here is a code example that led me astray in terms of thinking that it might be okay to modify some properties of "live" nodes off of the JavaFX Application thread. In this particle generator, the Node subclass Canvas is being modified intensely: 20,000 objects per 60 fps frame are having location and other attributes altered.

https://gist.github.com/Roland09/71ef45f14d0ec2a353e6

Is the animation timer actually on the JavaFX Application thread? It is a separate thread, it seems to me.

Here's a link to watch the particle generator in action:
http://wecode4fun.blogspot.co.at/2015/07/particles.html

<a href="http://www.youtube.com/v/1Nx5Be9BDYg?version=3&amp;hl=en_US&amp;start=" target="_blank">http://www.youtube.com/v/1Nx5Be9BDYg?version=3&amp;hl=en_US&amp;start=</a>

Anyway, nothing dire is happening. So, I am wondering what is going on. Why doesn't this program crash on a regular basis? Could it be that the only thing of concern is that some of the property references are being updated during a render iteration, and the differences between old vs. new values do not matter to this process?

I'm having trouble finding more information. The Node documentation does clearly state that modifications to a live node should be done on the FX Application thread. Will continue researching.

music and music apps: http://adonax.com
Offline philfrei
« Reply #8 - Posted 2017-01-04 03:43:05 »

I think I have a resolution to the concern given by @nsigma. The situation where I was modifying "live" Nodes from "outside" the FX Application thread turns out to have been an incorrect framing of the situation that was occurring.

The Application API has the following quote.

Quote
Threading

JavaFX creates an application thread for running the application start method, processing input events, and running animation timelines. Creation of JavaFX Scene and Stage objects as well as modification of scene graph operations to live objects (those objects already attached to a scene) must be done on the JavaFX application thread.

Thus, the code areas from where it is okay to modify the live nodes are actually pretty substantial. This would explain why I am able to modify opacity values from a method called by the AnimationTimer. I'm also able to remove the TitleBlocks node via this same method--and not throw the "not on FX application thread" exception.

The thread that was throwing the exception before was actually my Audio thread, while I was still within a NoteListener callback. I've rewritten the NoteListener so now it flips a switch that tells the update() method (on the AnimationTimer thread) to do the remove(node).

The NoteListener callbacks really need to be terse anyway (yes, never block the Audio thread!), nothing more than flipping a switch for the AnimationTimer thread to do the brunt of the work.

music and music apps: http://adonax.com
Offline nsigma
« Reply #9 - Posted 2017-01-04 10:54:24 »

Is the animation timer actually on the JavaFX Application thread? It is a separate thread, it seems to me.

No, the callbacks are on the JavaFX Application thread, same as the Swing Timer actions are called on the EDT.  That's the whole point of these classes.

You might be better using Platform.invokeLater(..) from your audio thread.

Don't assume all the places that require updates on the FX thread will throw exceptions if you're not on it.  This is unusual, as it forces the cost of checking what thread you're on for all usage - I assume there's a good reason why some of these methods do that, perhaps due to native code interactions.

Praxis LIVE - hybrid visual IDE for (live) creative coding
Pages: [1]
  ignore  |  Print  
 
 

 
Riven (397 views)
2019-09-04 15:33:17

hadezbladez (5280 views)
2018-11-16 13:46:03

hadezbladez (2204 views)
2018-11-16 13:41:33

hadezbladez (5544 views)
2018-11-16 13:35:35

hadezbladez (1150 views)
2018-11-16 13:32:03

EgonOlsen (4585 views)
2018-06-10 19:43:48

EgonOlsen (5462 views)
2018-06-10 19:43:44

EgonOlsen (3119 views)
2018-06-10 19:43:20

DesertCoockie (4016 views)
2018-05-13 18:23:11

nelsongames (4708 views)
2018-04-24 18:15:36
A NON-ideal modular configuration for Eclipse with JavaFX
by philfrei
2019-12-19 19:35:12

Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!