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

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

我有以下代码设置一定大小的窗口。 它还从外部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() { @Override public void handle(ActionEvent event) { primaryStage.close(); } }); menuGame.getItems().addAll(newGame,new SeparatorMenuItem(),exit); menuBar.getMenus().addAll(menuGame); Image image = new Image("http://sofzh.miximages.com/java/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(); } 

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

sizedefaultsizeresize

 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() { @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 imageViewProperty = new SimpleObjectProperty(); public ObjectProperty 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() { @Override public void changed(ObservableValue arg0, ImageView oldIV, ImageView newIV) { if (oldIV != null) { getChildren().remove(oldIV); } if (newIV != null) { getChildren().add(newIV); } } }); this.imageViewProperty.set(imageView); } } 

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

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

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

相关属性:

  • 有一个scale属性可以应用于任何节点。
  • 节点还具有可应用Scale的变换列表 。
  • ImageView具有fitWidth和fitHeight属性(在其他答案中演示了这一点)。

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

另一种可能的方法是使用Region子类(例如Pane),它具有已定义的CSS样式类或id,然后将CSS中的图像定义为背景 。 关于CSS定义图像的好处是,您可以使用其他基于CSS的属性来定义事物,例如图像的大小调整,缩放,定位和重复。 如果需要,也可以通过编程方式设置此背景,而不是通过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()); } 

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

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

您是想要调整实际图像的大小 ,还是只是为了居中?

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

另外,请小心你的图像,因为它是一个png图像。 我对那里的重新resize(实际图像或透明背景)有点怀疑。

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