在 JavaFX 中调整窗口大小时如何调整图像大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22993550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to resize an image when resizing the window in JavaFX
提问by Tony
I want an image to be resized automatically when the user drags the main window. Is that possible?
我希望在用户拖动主窗口时自动调整图像大小。那可能吗?
I have the following code that sets a window of a certain size. It also loads the image from an external URL.
我有以下代码可以设置特定大小的窗口。它还从外部 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();
}
采纳答案by jewelsea
Applying the solution to JavaFx image resizingto your sample code and resizing the window results in different image sizes for me.
将解决JavaFx 图像大小调整的解决方案应用于您的示例代码并调整窗口大小会为我带来不同的图像大小。
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);
}
}
Alternate approaches and extra information based upon comments
基于评论的替代方法和额外信息
If you have to do all that, then it's a weakness in he JavaFX platform. Ideally I would expect there to have been a scale property on the image that one could set so that it uses the SceneGraph to determine it's size.
如果您必须做所有这些,那么这是 JavaFX 平台的一个弱点。理想情况下,我希望图像上有一个可以设置的缩放属性,以便它使用 SceneGraph 来确定它的大小。
The solution presented above is just one answer, there are others possible. The scene graph can be used by binding various properties to the width and height of the parent node or by overriding layoutChildrenin the parent node.
上面提出的解决方案只是一个答案,还有其他可能的答案。可以通过将各种属性绑定到父节点的宽度和高度或通过覆盖父节点中的layoutChildren来使用场景图。
Related properties:
相关属性:
- There is a scale propertywhich can be applied to any node.
- A node also has a transform listto which a Scalemay be applied.
- ImageView has a fitWidthand fitHeight properties (use of this is demonstrated in other answers).
I prefer the region subclass approach to a scale property or transform based approach because then the image is automatically sized based upon the layout manager. The ImageViewPane defined above is just a one-off definition class which can be reused as much as you want, the actual application code to use an ImageView or ImageViewPane is pretty much equivalent.
我更喜欢区域子类方法而不是基于缩放属性或变换的方法,因为这样图像会根据布局管理器自动调整大小。上面定义的 ImageViewPane 只是一个一次性定义类,可以根据需要重复使用,使用 ImageView 或 ImageViewPane 的实际应用程序代码几乎是等效的。
Another possible approach is to use a Region subclass (such as a Pane), which has a defined CSS style class or id and then to define the image in CSS as a background. The nice thing about a CSS defined image is that you can then use additional CSS based attributes to define things, like sizing, scaling, positioning and repeats for the image. This backgroundcan also be set programmaticallyif desired rather than via CSS.
另一种可能的方法是使用 Region 子类(例如 Pane),它具有定义的 CSS 样式类或 id,然后在 CSS中将图像定义为背景。CSS 定义图像的好处在于,您可以使用额外的基于 CSS 的属性来定义图像的大小、缩放、定位和重复。如果需要,也可以通过编程而不是通过 CSS设置此背景。
Related question:
相关问题:
To maintain proportional height and width of the image
保持图像的高度和宽度成比例
The following code can be used in the ImageViewPane class provided above:
在上面提供的 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());
}
回答by GGrec
Are you looking to resize an actual image, or just to center it?
您是要调整实际图像的大小,还是只是将其居中?
You can try this: VBox.setVgrow(root, Priority.ALWAYS);
and see if that's what you want.
你可以试试这个:VBox.setVgrow(root, Priority.ALWAYS);
看看这是否是你想要的。
Also, be careful with you image, because it's a png
image. I'm a bit skeptic regarding what's resized there (the actual image or the transparent background).
另外,要小心你的形象,因为它是一个png
形象。我对那里调整大小的内容(实际图像或透明背景)持怀疑态度。
回答by Andrew S
I know this is old but someone like me may stumble upon this so here is my solution. I am assuming that rootis the root node of your scene. However, this should work if your parent node of the ImageViewis any child of Pane.
我知道这很旧,但像我这样的人可能会偶然发现这个,所以这是我的解决方案。我假设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());
回答by Blu
Just use a normal pane with a background image, here the css needed.
只需使用带有背景图像的普通窗格,这里需要 css。
#titleImage{
-fx-background-image: url("../img/logo.png");
-fx-background-repeat: stretch;
-fx-background-position: center center;
}