如何在JavaFX中调整窗口大小时调整图像大小

时间:2014-04-10 16:18:35

标签: java eclipse autoresize

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

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

}

4 个答案:

答案 0 :(得分:8)

将解决方案JavaFx image resizing应用于示例代码并调整窗口大小会为我带来不同的图像尺寸。

sizedefault sizeresize

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

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

  

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

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

相关属性:

我更喜欢区域子类方法来进行缩放属性或基于变换的方法,因为然后根据布局管理器自动调整图像大小。上面定义的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());
}

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

您是期待resize an actual image,还是只是为了居中?

您可以尝试:VBox.setVgrow(root, Priority.ALWAYS);并查看这是否是您想要的。

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

答案 3 :(得分:0)

我知道这已经过时了,但像我这样的人可能偶然发现这一点,所以这是我的解决方案。我假设 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());