【问题标题】:How to resize an image when resizing the window in JavaFX在 JavaFX 中调整窗口大小时如何调整图像大小
【发布时间】:2014-05-24 11:38:33
【问题描述】:

我希望在用户拖动主窗口时自动调整图像大小。这可能吗?

我有以下代码可以设置一定大小的窗口。它还从外部 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();

}

【问题讨论】:

标签: java eclipse autoresize


【解决方案1】:

只需使用带有背景图像的普通窗格,这里需要 css。

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

【讨论】:

    【解决方案2】:

    JavaFx image resizing 的解决方案应用于您的示例代码并调整窗口大小会导致我的图像大小不同。

    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);
        }
    }
    

    基于 cmets 的替代方法和额外信息

    如果您必须这样做,那么这是 JavaFX 平台的一个弱点。理想情况下,我希望图像上有一个可以设置的比例属性,以便它使用 SceneGraph 来确定它的大小。

    上述解决方案只是一个答案,还有其他可能的答案。可以通过将各种属性绑定到父节点的宽度和高度或通过覆盖父节点中的layoutChildren来使用场景图。

    相关属性:

    • 有一个scale property 可以应用于任何节点。
    • 一个节点也有一个transform list,可以应用Scale
    • ImageView 具有 fitWidth 和 fitHeight 属性(其他答案中演示了此属性的使用)。

    我更喜欢区域子类方法而不是缩放属性或基于变换的方法,因为这样图像会根据布局管理器自动调整大小。上面定义的 ImageViewPane 只是一个一次性的定义类,可以根据需要重复使用,使用 ImageView 或 ImageViewPane 的实际应用程序代码几乎是等效的。

    另一种可能的方法是使用 Region 子类(例如 Pane),它具有定义的 CSS 样式类或 id,然后定义 image in CSS as a background。 CSS 定义图像的好处是,您可以使用其他基于 CSS 的属性来定义图像的大小、缩放、定位和重复。如果需要,这个background 也可以是set programmatically,而不是通过 CSS。

    相关问题:

    保持图片的高度和宽度成比例

    在上面提供的 ImageViewPane 类中可以使用以下代码:

    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());
    }
    

    【讨论】:

    • 如果你必须做所有这些,那么这是 JavaFX 平台的一个弱点。理想情况下,我希望图像上有一个可以设置的比例属性,以便它使用 SceneGraph 来确定它的大小。
    • @AndrewS 有scaleX and scaleY properties on ImageView。此外,您可以在 ImageView 上设置transforms,包括scale 变换。
    【解决方案3】:

    我知道这是旧的,但像我这样的人可能会偶然发现这个,所以这是我的解决方案。我假设 root 是场景的根节点。但是,如果 ImageView 的父节点是 Pane 的任何子节点,这应该可以工作。

    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());
    

    【讨论】:

    • 下面两条线中的center到底是什么?
    • 中心是图像的父级或正在改变大小的容器。这很好用。
    • 完美解决方案。我使用 center 作为 vbox 并添加了:imv.setPreserveRatio(true); imv.setSmooth(true);
    【解决方案4】:

    您是在寻找resize an actual image,还是只是将其居中?

    你可以试试这个:VBox.setVgrow(root, Priority.ALWAYS); 看看是不是你想要的。

    另外,请注意您的图片,因为它是png 的图片。我对那里调整大小的内容(实际图像或透明背景)有点怀疑。

    【讨论】:

    • 我不想要那个。要提供线索,请打开 Windows 7 扫雷器并通过拖动来调整窗口大小。您会注意到网格中的图像(正方形)会相应地调整大小
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 2010-12-21
    • 2017-04-29
    • 2023-03-22
    • 2021-10-02
    相关资源
    最近更新 更多