So ändern Sie die Größe eines Bildes, wenn Sie die Größe des Fensters in JavaFX ändern

Lesezeit: 6 Minuten

Benutzer-Avatar
Toni

Ich möchte, dass die Größe eines Bildes automatisch geändert wird, wenn der Benutzer das Hauptfenster zieht. Ist das möglich?

Ich habe den folgenden Code, der ein Fenster einer bestimmten Größe festlegt. Es lädt auch das Bild von einer externen URL.

@Override
public void start(Stage primaryStage) {

    MenuBar menuBar=new MenuBar();
    Menu menuGame = new Menu("Game");
    MenuItem newGame = new MenuItem("New Game                F1");
    MenuItem exit = new MenuItem("Exit                            F2");
    exit.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            primaryStage.close();
        }

    });
    menuGame.getItems().addAll(newGame,new SeparatorMenuItem(),exit);
    menuBar.getMenus().addAll(menuGame);

    Image image = new Image("http://docs.oracle.com/javafx/"
    + "javafx/images/javafx-documentation.png");
    ImageView imageView = new ImageView();
    imageView.setImage(image);


    VBox vbox=new VBox();
    StackPane root=new StackPane();
    root.getChildren().addAll(imageView);

    vbox.getChildren().addAll(menuBar,root);

    Scene scene= new Scene(vbox,400,400);
    primaryStage.setScene(scene);

    primaryStage.setMaxHeight(800);
    primaryStage.setMinHeight(400);
    primaryStage.setMaxWidth(1000);
    primaryStage.setMinWidth(800);

    primaryStage.setTitle("Minesweeper");
    primaryStage.show();

}

  • mögliches Duplikat der Größenänderung von JavaFx-Bildern

    – Juwelensee

    10. April 2014 um 19:03 Uhr

  • Mögliches Duplikat von Bilder an den übergeordneten Knoten anpassen

    – Steve Krüger

    9. Februar 2016 um 18:19 Uhr

Benutzer-Avatar
Juwelsee

Das Anwenden der Lösung auf die Größenänderung von JavaFx-Bildern auf Ihren Beispielcode und die Größenänderung des Fensters führt bei mir zu unterschiedlichen Bildgrößen.

Größenvorgabe
Größeändern

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.event.*;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class ImageResizer extends Application {
    @Override
    public void start(Stage primaryStage) {
        MenuBar menuBar=new MenuBar();
        Menu menuGame = new Menu("Game");
        MenuItem newGame = new MenuItem("New Game                F1");
        MenuItem exit = new MenuItem("Exit                            F2");
        exit.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                primaryStage.close();
            }
        });
        menuGame.getItems().addAll(newGame,new SeparatorMenuItem(),exit);
        menuBar.getMenus().addAll(menuGame);

        Image image = new Image("http://docs.oracle.com/javafx/"
                + "javafx/images/javafx-documentation.png");
        ImageView imageView = new ImageView();
        imageView.setImage(image);

        ImageViewPane viewPane = new ImageViewPane(imageView);

        VBox vbox=new VBox();
        StackPane root=new StackPane();
        root.getChildren().addAll(viewPane);

        vbox.getChildren().addAll(menuBar,root);
        VBox.setVgrow(root, Priority.ALWAYS);

        Scene scene= new Scene(vbox,200,200);
        primaryStage.setScene(scene);

        primaryStage.setMaxHeight(400);
        primaryStage.setMinHeight(200);
        primaryStage.setMaxWidth(500);
        primaryStage.setMinWidth(400);

        primaryStage.setTitle("Minesweeper");
        primaryStage.show();

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





/*
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 */


/**
 *
 * @author akouznet
 */
class ImageViewPane extends Region {

    private ObjectProperty<ImageView> imageViewProperty = new SimpleObjectProperty<ImageView>();

    public ObjectProperty<ImageView> imageViewProperty() {
        return imageViewProperty;
    }

    public ImageView getImageView() {
        return imageViewProperty.get();
    }

    public void setImageView(ImageView imageView) {
        this.imageViewProperty.set(imageView);
    }

    public ImageViewPane() {
        this(new ImageView());
    }

    @Override
    protected void layoutChildren() {
        ImageView imageView = imageViewProperty.get();
        if (imageView != null) {
            imageView.setFitWidth(getWidth());
            imageView.setFitHeight(getHeight());
            layoutInArea(imageView, 0, 0, getWidth(), getHeight(), 0, HPos.CENTER, VPos.CENTER);
        }
        super.layoutChildren();
    }

    public ImageViewPane(ImageView imageView) {
        imageViewProperty.addListener(new ChangeListener<ImageView>() {

            @Override
            public void changed(ObservableValue<? extends ImageView> arg0, ImageView oldIV, ImageView newIV) {
                if (oldIV != null) {
                    getChildren().remove(oldIV);
                }
                if (newIV != null) {
                    getChildren().add(newIV);
                }
            }
        });
        this.imageViewProperty.set(imageView);
    }
}

Alternative Ansätze und zusätzliche Informationen basierend auf Kommentaren

Wenn Sie das alles tun müssen, dann ist es eine Schwäche der JavaFX-Plattform. Idealerweise würde ich erwarten, dass es eine Skalierungseigenschaft für das Bild gibt, die man so einstellen könnte, dass es den SceneGraph verwendet, um seine Größe zu bestimmen.

Die oben vorgestellte Lösung ist nur eine Antwort, es sind noch andere möglich. Der Szenengraph kann verwendet werden, indem verschiedene Eigenschaften an die Breite und Höhe des übergeordneten Knotens gebunden oder überschrieben werden LayoutKinder im übergeordneten Knoten.

Verwandte Eigenschaften:

  • Da ist ein Scale-Eigenschaft die auf jeden Knoten angewendet werden kann.
  • Ein Knoten hat auch eine Liste transformieren wozu ein Skala angewendet werden dürfen.
  • ImageView hat eine fitBreite und fitHeight-Eigenschaften (die Verwendung davon wird in anderen Antworten gezeigt).

Ich bevorzuge den Ansatz der Bereichsunterklasse gegenüber einem auf Skalierungseigenschaft oder Transformation basierenden Ansatz, weil dann die Größe des Bilds basierend auf dem Layout-Manager automatisch angepasst wird. Das oben definierte ImageViewPane ist nur eine einmalige Definitionsklasse, die beliebig oft wiederverwendet werden kann, der eigentliche Anwendungscode zur Verwendung eines ImageView oder ImageViewPane ist ziemlich äquivalent.

Ein anderer möglicher Ansatz besteht darin, eine Region-Unterklasse (z. B. einen Bereich) zu verwenden, die eine definierte CSS-Stilklasse oder -ID hat, und dann die zu definieren Bild in CSS als Hintergrund. Das Schöne an einem CSS-definierten Bild ist, dass Sie dann zusätzliche CSS-basierte Attribute verwenden können, um Dinge wie Größe, Skalierung, Positionierung und Wiederholungen für das Bild zu definieren. Dies Hintergrund kann auch sein programmgesteuert festlegen auf Wunsch statt per CSS.

Verwandte Frage:

  • Anpassen der Bildgröße an den übergeordneten Knoten

Um die proportionale Höhe und Breite des Bildes beizubehalten

Der folgende Code kann in der oben bereitgestellten ImageViewPane-Klasse verwendet werden:

if (imageView.isPreserveRatio()) {
    if (getHeight() > getWidth()) {
        imageView.setFitWidth(getWidth());
        imageView.setFitHeight(0);
    } else {
        imageView.setFitWidth(0);
        imageView.setFitHeight(getHeight());
    }
} else {
    imageView.setFitWidth(getWidth());
    imageView.setFitHeight(getHeight());
}

  • Wenn Sie das alles tun müssen, dann ist es eine Schwäche der JavaFX-Plattform. Idealerweise würde ich erwarten, dass es eine Skalierungseigenschaft für das Bild gibt, die man so einstellen könnte, dass es den SceneGraph verwendet, um seine Größe zu bestimmen.

    – Andreas S

    16. März 2016 um 5:57 Uhr

  • @AndrewS gibt es scaleX- und scaleY-Eigenschaften auf ImageView. Zusätzlich können Sie einstellen transformiert auf der ImageView, einschließlich Skala transformiert.

    – Juwelensee

    18. Dezember 2019 um 20:45 Uhr

Ich weiß, das ist alt, aber jemand wie ich könnte darüber stolpern, also hier ist meine Lösung. Ich gehe davon aus Wurzel ist der Wurzelknoten Ihrer Szene. Dies sollte jedoch funktionieren, wenn Ihr übergeordneter Knoten der Bildansicht ist irgendein Kind von Feld.

imv = new ImageView();  
root.getChildren().add(imv);
Image image = new Image(Main.class.getResourceAsStream("image.png"))
imv.setImage(image);

imv.fitWidthProperty().bind(center.widthProperty());
imv.fitHeightProperty().bind(center.heightProperty());

  • was genau ist das center in den beiden unteren Zeilen?

    – Fabio

    10. Juli 2017 um 15:42 Uhr

  • Das Zentrum ist das übergeordnete Element des Bildes oder des Containers, dessen Größe sich ändert. Das funktioniert sehr gut.

    – dnp

    3. Februar 2020 um 5:47 Uhr

  • Perfekte Lösung. Ich habe center als vbox verwendet und auch hinzugefügt: imv.setPreserveRatio(true); imv.setSmooth (true);

    – KenobiBastila

    5. Juni 2020 um 22:23 Uhr

Verwenden Sie einfach ein normales Fenster mit einem Hintergrundbild, hier das benötigte CSS.

#titleImage{
    -fx-background-image: url("../img/logo.png");
    -fx-background-repeat: stretch; 
    -fx-background-position: center center;
}

Benutzer-Avatar
georgisch

Möchten Sie die Größe eines tatsächlichen Bildes ändern oder es nur zentrieren?

Sie können dies versuchen: VBox.setVgrow(root, Priority.ALWAYS); und schau ob du das willst.

Seien Sie auch vorsichtig mit Ihrem Bild, denn es ist a png Bild. Ich bin etwas skeptisch, was dort geändert wird (das tatsächliche Bild oder der transparente Hintergrund).

1018300cookie-checkSo ändern Sie die Größe eines Bildes, wenn Sie die Größe des Fensters in JavaFX ändern

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy