Lofi Peng
Lofi Peng

Reputation: 19

How can I keep background image stretched to gridpane on resize?

I'm trying to use a gridpane with a background image (an image with defined edges, not a continuous texture) . The image needs to stretch with the gridpane when resizing the app. However, it doesn't seem to work properly.

Depending on wether "contain" or "cover" are set true/false in the BackgroundSize arguments the following happens:

Either: the image scales with its own aspect ratio, meaning it doesn't keep the ratio of the gridpane (tested this by putting a boarder around the gridpane).

Or: the image covers the gripane at all times, but either the right side or the bottom of the image looks cut-off at either the right side or the bottom edge of the gridpane, depending on how the window is resized.

I was told there is an option to "stretch" the background to a pane. But I can't seem to find this option anywhere.

With CSS -fx-background-size: stretch; is does the stretching perfectly, but unfortunately, CSS doesn't like .pngs with alpha sections.

@FXML
private GridPane gridView;
@FXML
private void initialize() {
   BackgroundSize backgroundSize = new BackgroundSize(0.6, 0.8, true, true, true, true);

   BackgroundImage image = new BackgroundImage(new Image("example_image.png"),
      BackgroundRepeat.NO_REPEAT,
      BackgroundRepeat.NO_REPEAT,
      BackgroundPosition.CENTER,
      backgroundSize
   );
   gridView.setBackground(new Background(image)); 

Example

Upvotes: 0

Views: 600

Answers (1)

James_D
James_D

Reputation: 209724

If you want the image to stretch to fill the pane completely in both directions, scaling independently (i.e. without preserving aspect ratio) in each, use

BackgroundSize backgroundSize = new BackgroundSize(1, 1, true, true, false, false);

Setting the second and third parameters to true ensures that the first two are interpreted as "percentages" (or more accurately, proportions), so this will force the background image to be 100% of the width and height of the pane. The last two are contain and cover, either of which preserves the images aspect ratio. See the documentation.

Here is a complete example:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class BackgroundImageStretch extends Application {
    public static void main(String[] args) {launch(args);}

    @Override
    public void start(Stage stage) {
        BackgroundSize backgroundSize = new BackgroundSize(1, 1, true, true, false, false);
        BackgroundImage image = new BackgroundImage(createImage(),
                BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT,
                BackgroundPosition.CENTER,backgroundSize);

        Pane root = new Pane();
        root.setBackground(new Background(image));
        Scene scene = new Scene(root, 400, 400);
        stage.setScene(scene);
        stage.show();
    }

    private Image createImage() {
        WritableImage img = new WritableImage(400, 400);
        PixelWriter pw = img.getPixelWriter();
        for (int x = 0 ; x < 400; x++) {
            for (int y = 0 ; y < 400 ; y++) {
                Color color = x < 5 || x > 394 || y < 5 || y > 394 ? Color.YELLOW : Color.LIGHTBLUE ;
                pw.setColor(x, y, color);
            }
        }
        return img ;
    }
}

enter image description here

enter image description here

enter image description here

Upvotes: 3

Related Questions