I'd like to hear from the others on this. I don't see any fundamental
problem with having the play/pause/stop methods wrap their
implementation in a runLater (if not on the FX Application thread
already), and documenting that it does so, if we can get general agreement.
-- Kevin
On 1/24/2024 5:29 AM, Jurgen Doll wrote:
Hi Kevin
If I may make one more final appeal then to an alternative solution
please.
Could we then instead of throwing an Exception rather invoke runLater
if needed inside play, stop, and resume.
Putting the onus on the developer is fine if it is the developer that
is invoking the call, but if it's in a library then it's a no go.
In my application I have two libraries that I know of where this
happens. The major problem is that with FX22 as it now stands my
application just crashes because play() does an FX thread check and
throws an Exception which it never did before. There are bound to be
other applications out there that are going to find themselves in a
similar position.
PLEASE !
Regards
Jurgen
On Wed, 24 Jan 2024 15:15:31 +0200, Kevin Rushforth
<kevin.rushfo...@oracle.com> wrote:
Thank you to Jurgen for raising the question and to Nir, John, and
Michael for evaluating it.
I conclude that there is insufficient motivation to revert the
change in behavior implemented by JDK-8159048 to allow calling the
play/pause/stop methods of Animation on a background thread. Doing
so without making it fully multi-thread-safe would be asking for
problems, and making it fully multi-thread-safe would be a fair
bit of work to do it right without a clear benefit.
We will proceed with the current approach and let JDK-8159048
stand. Further, we will proceed with
https://bugs.openjdk.org/browse/JDK-8324219 which is under review
in https://github.com/openjdk/jfx/pull/1342
-- Kevin
On 1/24/2024 12:30 AM, Nir Lisker wrote:
After playing around with the code sample, I think that this is
not the right way to use the animation. The reason is that there
is no point in starting the animation before the control is
attached to the scenegraph, or even made visible. A small
refactoring where, e.g., the controller class exposes a method to
start the animation in onSucceeded or just calls it on the FX
thread is enough. I never start an animation as part of the
construction because it's not the right time. John suggested
tying the lifecycle of the animation to the showing of the node,
which also solves the problem.
There are animations like PauseTransition or other
non-interfering Timelines that could reasonably be run on a
background thread. Or maybe just on an unconnected control. This
could be a reason to not limit animation methods to the FX thread
at the expense of possible user errors, but document the pitfall.
I don't see a good use case for modifying controls in a
background thread while still interacting with the scenegraph,
hence for adding multithread support.
- Nir
On Mon, Jan 22, 2024, 12:59 Jurgen Doll <jav...@ivoryemr.co.za>
wrote:
Here's an example as requested by Nir:
publicclassFxTimeLineTest extendsApplication
{
privateBorderPane bp= newBorderPane( newLabel("Loading") );
publicstaticvoidmain( String[] args) {
launch( FxTimeLineTest.class, args);
}
@Override
publicvoidstart( Stage primaryStage) throwsException {
newThread( newLoadScene() ).start();
primaryStage.setScene( newScene( bp, 300, 200 ) );
primaryStage.setTitle( "Memory Usage");
primaryStage.show();
}
privateclassLoadScene extendsTask<Parent> {
@OverrideprotectedParent call() throwsException {
Parent p= FXMLLoader.load( getClass(
).getResource("TestView.fxml") );
Thread.sleep( 1000 );
returnp;
}
@Overrideprotectedvoidsucceeded() {
bp.setCenter( getValue() );
}
@Overrideprotectedvoidfailed() {
getException().printStackTrace();
}
}
}
------------------------------------------------------------------------------------------------------
publicclassTestView
{
@FXMLprivateLabel memory;
privatestaticfinaldoubleMEGABYTE= 1024 * 1024;
@FXMLprivatevoidinitialize()
{
varupdater= newTimeline
(
newK eyFrame( Duration.seconds(2.5), event->
{
varruntime= Runtime.getRuntime();
doublemaxMemory= runtime.maxMemory() / MEGABYTE;
doubleusedMemory= (runtime.totalMemory() -
runtime.freeMemory()) / MEGABYTE;
memory.setText( (int) usedMemory+ " MB / "+ (int) maxMemory+"
MB");
})
);
updater.setCycleCount(Animation.INDEFINITE); // This FXML is
being loaded on a background thread
updater.play();
}
}
------------------------------------------------------------------------------------------------------
TestView.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.StackPane?>
<StackPane xmlns:fx="http://javafx.com/fxml/1"
fx:controller="TestView">
<children>
<Label fx:id="memory" text="Current / Max MB" >
<properties hashCode="12345" />
</Label>
</children>
</StackPane>
On Sat, 20 Jan 2024 17:08:41 +0200, Nir Lisker
<nlis...@gmail.com> wrote:
Hi Jurgen,
What I'm confused about the most is what it is you are
actually trying to do that necessitates the use of
animations outside of the FX thread. You said that you
need to initialize controls on another thread, and that
you are using Task (both of which are fine), but how does
playing animations relate? Playing an animation is
something that is done explicitly, usually in order to
manipulate data. Can you give a real use case, like a
minimized version of what you're doing?
- Nir
--
Using Opera's mail client: http://www.opera.com/mail/