将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来使用场景图。
相关属性:
我更喜欢区域子类方法而不是缩放属性或基于变换的方法,因为这样图像会根据布局管理器自动调整大小。上面定义的 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());
}