JDK-8154846 : SwingNode does not resize when content size constraints are changed
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 8u77
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: other
  • CPU: x86
  • Submitted: 2016-04-19
  • Updated: 2023-10-19
  • Resolved: 2023-10-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 22
22 b20Fixed
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_77"
Java(TM) SE Runtime Environment (build 1.8.0_77-b03)
Java HotSpot(TM) 64-Bit Server VM (build 25.77-b03, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 10.0.10586]

A DESCRIPTION OF THE PROBLEM :
SwingNode does not update its internal cache of Swing pref/max/min height and widths when its JComponent content's corresponding size constraints are updated.  As such, it isn't resized to honor those size constraints.

The private implementation class SwingNodeContent does contain methods preferredSizeChanged(), maximumSizeChanged(), and minimumSizeChanged(), but these are only called once from JLightweightFrame.setContent() when the JComponent is first installed via SwingNode.setContent().

JLightweightFrame does install a PropertyChangeListener for "preferredSize", "maximumSize", and "minimumSize" properties, but this only happens via a ContainerListener which is not added until after the content has already been added to the content pane.  The component installed via SwingNode.setContent() never gets these property change listeners added.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- Create a SwingNode
- Set a JComponent as the SwingNode's content
- Add the SwingNode to a Scene/Stage and show it
- Modify the JComponent's pref/max/min size


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
According to the documentation for the SwingNode.resize() method: "Applications should not invoke this method directly. If an application needs to directly set the size of the SwingNode, it should set the Swing component's minimum/preferred/maximum size constraints which will be propagated correspondingly to the SwingNode and it's parent will honor those settings during layout."

ACTUAL -
The SwingNode's size does NOT honor its Swing components minimum/preferred/maximum size constraints.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class SwingNodeResize extends Application
{
    StackPane root;

    @Override
    public void start(Stage primaryStage)
    {
        SwingNode swingNode = new SwingNode();

        init(swingNode);

        root = new StackPane(new Rectangle(500, 500, Color.RED), swingNode);
        Scene scene = new Scene(root);

        primaryStage.setTitle("SwingNode Resize");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void init(final SwingNode node)
    {
        SwingUtilities.invokeLater(() ->
        {
            JButton button = new JButton("Click me!");
            button.addActionListener(event ->
            {
                Dimension buttonSize = button.getSize();
                buttonSize.setSize(buttonSize.getWidth() * 2, buttonSize.getHeight() * 2);

                button.setPreferredSize(buttonSize);
                button.setMinimumSize(buttonSize);
                button.setMaximumSize(buttonSize);
                button.setSize(buttonSize);

                System.out.println("Button size: " + button.getPreferredSize());
                Platform.runLater(() -> System.out.println("SwingNode size: " + node.prefWidth(-1) + " " + node.prefHeight(-1)));
            });

            node.setContent(button);
        });
    }

    public static void main(String[] args)
    {
        launch(args);
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
- Removing the JComponent from the SwingNode
- Modify the JComponent's size constraints
- Reinstall the JComponent as the SwingNode's content


Comments
Changeset: 37eb9860 Author: Prasanta Sadhukhan <psadhukhan@openjdk.org> Date: 2023-10-16 09:01:57 +0000 URL: https://git.openjdk.org/jdk/commit/37eb98604f4e2c241d959c7e2b337beb047421da
16-10-2023

Since the proposed fix is in the interop code in java.desktop, I'm changing the component to client-libs/javax.swing
04-10-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/15960 Date: 2023-09-28 09:43:25 +0000
28-09-2023

The LightweightContent object in SwingNode is not receiving any notifications of the change in preferred/min/max size. It looks like JLightweightFrame hard-codes notifications of these values when the content is set, and it also installs listeners, but only the hard-coded notifications make it through. I'm reassigning to Swing for further evaluation.
28-04-2016