javajavafxmediaview

How do I make JavaFX MediaView stretch and shrink media to fill/fit parent container?


How do I make JavaFX MediaView stretch and shrink media to fill/fit parent container?

There's already a question here:

How do I make JavaFX MediaView stretch media to fill parent container?

and the solution with this code:

<Pane fx:id="mediaViewPane">
  <children>
     <MediaView fx:id="videoView" fitHeight="${mediaViewPane.height}" fitWidth="${mediaViewPane.width}" layoutX="1.0" />
  </children>
</Pane>

works for making the video bigger to fill the container, but it doesn't allow the container to be smaller than the size of the video, so, it doesn't shrink, it just starts hiding controls as they fall outside the scene.

Any ideas how to stretch but also shrink the MediaView to fit?


Solution

  • I have achieved this, although I'm not super confident about this being the best approach. First, as fabian pointed out, I need to set the MediaView as not managed so that the parent Pane can be resized to any size without the MediaView constraining it:

    <Pane fx:id="mediaViewPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="0.0" minWidth="0.0">
        <MediaView fx:id="mediaView" StackPane.alignment="CENTER" managed="false"/>
    </Pane>
    

    Then, on a rezise event, I resize the MediaView to fit in the parent, then get the actual size of the video and offset it to center:

    InvalidationListener resizeMediaView = observable -> {
        mediaView.setFitWidth(mediaViewPane.getWidth());
        mediaView.setFitHeight(mediaViewPane.getHeight());
    
        // After setting a big fit width and height, the layout bounds match the video size. Not sure why and this feels fragile.
        Bounds actualVideoSize = mediaView.getLayoutBounds();
        mediaView.setX((mediaView.getWidth() - actualVideoSize.getWidth()) / 2);
        mediaView.setY((mediaView.getHeight() - actualVideoSize.getHeight()) / 2);
    };
    mediaViewPane.heightProperty().addListener(resizeMediaView);
    mediaViewPane.widthProperty().addListener(resizeMediaView);