JFXPanel ignores size change of root node

Artem Ananiev artem.ananiev at oracle.com
Mon Dec 17 04:49:45 PST 2012

On 12/17/2012 3:59 PM, Werner Lehmann wrote:
> Hi Artem,
> On 17.12.2012 12:09, Artem Ananiev wrote:
>> Just imagine the following scenario. Create a regular FX Stage and put a
>> 120x120 button inside. Then show the stage. Then set an action listener
>> to the button, so it changes the button size to 160x120. Will the stage
>> size change, when the button is clicked?
> coincidentally I tried that while you were typing up that email. The
> stage does not resize. Inspection in a breakpoint shows that also the
> scene.width does not change. So how would the stage know about it anyway...

Thanks for trying this. My assumption about JFXPanel behaving exactly 
like regular FX Stage was correct. If we want to "fix" it, the fix will 
be common for embedded and standalone windows.

At the API level we have code that calculates Scene's preferred size and 
resize Stage so it perfectly matches this Scene. It's only done a) when 
the window is being shown b) if the window size was not set explicitly. 
This code can be extracted into a public method to be called by 
application at arbitrary moment, close to AWT's Frame.pack().

Jasper, Richard, what do you think about this idea?

>> Could you try to leave JFXPanel as is, but set its scene to null and
>> back to your scene, please? I don't say it's the way it's supposed to
>> work, just an idea for workaround.
> This works - sometimes. If I keep clicking that button I get about 70%
> correct results and occasionally the JFXPanel did not resize as desired.
> Here's the kicker: sleeping for 10ms after setting the scene works
> reliably (on my machine and for this simple scene). 9ms is not enough:
>            r.setWidth(r.getWidth() == 160 ? 120 : 160);
>            Scene scene = getScene();
>            setScene(null);
>            setScene(scene);
>            sleep(10);
> Not exactly reassuring but better than before. Alternatively, the sleep
> can be moved to the EDT which also works:
>            r.setWidth(r.getWidth() == 160 ? 120 : 160);
>            Scene scene = getScene();
>            setScene(null);
>            setScene(scene);
>            SwingUtilities.invokeLater(new Runnable() {
>              @Override
>              public void run()
>              {
>                sleep(10);
>                invalidate();
>              }
>            });
> Some kind of strange race condition? Obviously I'd like to avoid any
> hardcoded sleeps... Also: am I supposed to invalidate on EDT, or not?
> Seems to work without.

invalidate(), as well as JComponent.revalidate(), is thread safe.

In general, it looks like a bug, we shouldn't depend on the timings. 
Please, file a new bug to JavaFX JIRA, but I can't guarantee it will be 
fixed in a few hours :)



>> In general, updating JFXPanel's preferred size upon FX scene
>> size/content changes looks like a valid request. It's not a pure
>> JFXPanel feature, though: we need to have a notification from Scene to
>> know that the window size should be updated.
> Scene has observable width/height properties. Not sure if those change
> but at least Scene.root.*anyboundsproperty* should do.
> Rgds
> Werner

More information about the openjfx-dev mailing list