是否可以使JavaFX中的ImageView响应? [英] Is it possible to make a ImageView in JavaFX responsive?
问题描述
这是我的代码:
< / image>< / ImageView>
< ImageView id = sample fitHeight = 25.0 fitWidth = 27.0 pickOnBounds = true reserveRatio = true GridPane.columnIndex = 15 GridPane.hgrow = ALWAYS GridPane.rowIndex = 24 GridPane.vgrow = ALWAYS>
< image>
<图片url = @ sample.png />
< / image>< / ImageView>
一种解决方案是创建 Region
子类,只包装 ImageView
。这比将 ImageView
的fit width / height属性与其父级绑定更好,因为将子级的尺寸绑定到其父级的尺寸可能会导致布局系统出现问题。
这里是一个例子:
导入javafx.beans.DefaultProperty;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Region;
@DefaultProperty( image)
公共类ResizableImageView扩展了区域{
/ * *************** ****************************************************** ****
* *
*属性*
* *
*********************** **************************************************** /
//-图片属性
私有最终ObjectProperty< Image>图像=
新的SimpleObjectProperty(this, image){
@Override
protected void invalidated(){
imageView.setImage(get());
}
};
public final void setImage(Image image){
this.image.set(image);
}
public final Image getImage(){
return image.get();
}
公共最终ObjectProperty< Image> imageProperty(){
返回图片;
}
// --preserveRatio属性
私有最终BooleanProperty prepareRatio =
new SimpleBooleanProperty(this, preserveRatio){
@Override
protected void invalidated(){
imageView.setPreserveRatio(get());
}
};
public final void setPreserveRatio(boolean reserveRatio){
this.preserveRatio.set(preserveRatio);
}
public final boolean isPreserveRatio(){
return reserveRatio.get();
}
public final BooleanProperty prepareRatioProperty(){
return reserveRatio;
}
/ * *********************************** **************************************
* *
*实例字段*
* *
****************************************** ********************************* /
私人最终ImageView imageView = new ImageView();
/ * **************************************** ********************************
* *
*构造函数*
* *
************************************************ *********************** /
public ResizableImageView(){
getStyleClass()。add( resizable-图片视图);
getChildren()。add(imageView);
}
public ResizableImageView(Image image){
this();
setImage(image);
}
/ * *********************************** **************************************
* *
*方法*
* *
******************************************* ******************************** /
@Override
受保护的void layoutChildren(){
double x = snappedLeftInset();
double y = snappedTopInset();
double w = getWidth()-x-snappedRightInset();
double h = getHeight()-y-snappedRightInset();
imageView.setFitWidth(w);
imageView.setFitHeight(h);
positionInArea(imageView,x,y,w,h,-1,HPos.CENTER,VPos.CENTER);
}
@Override
protected double computePrefWidth(double height){
double prefWidth = snappedLeftInset()+ snappedRightInset();
var image = getImage();
if(image!= null){
double requestWidth = image.getRequestedWidth();
prefWidth + =(requestedWidth> 0.0?requestWidth:image.getWidth());
}
return snapSizeX(prefWidth);
}
@Override
protected double computePrefHeight(double width){
double prefHeight = snappedTopInset()+ snappedBottomInset();
var image = getImage();
if(image!= null){
double requestHeight = image.getRequestedHeight();
prefHeight + =(requestedHeight> 0.0?requestHeight:image.getHeight());
}
return snapSizeY(prefHeight);
}
}
您可以设置 minWidth
, minHeight
, maxWidth
和 maxHeight
属性可控制图片的大小。
您可以使用来完成几乎相同的操作一个 BackgroundImage
。
var image =新图片(...);
var bgImage = new BackgroundImage(
image,
BackgroundRepeat.NO_REPEAT,
BackgroundRepeat.NO_REPEAT,
BackgroundPosition.CENTER,
new BackgroundSize(1.0,1.0 ,true,true,false,false)
);
var region = new Region();
region.setBackground(new Background(bgImage));
这将导致图像填充整个 Region
,就像在 ResizableImageView $中将
preserveRatio
设置为 false
一样c $ c>示例。如果您希望它的行为就像 preserveRatio
设置为 true
一样,请使用以下 BackgroundSize
:
new BackgroundSize(1.0,1.0,true,true,真假);
差异是第五个参数,包含
,已从 false
更改为 true
。查看文档以了解更多信息每个参数的作用。
请注意,以这种方式使用 BackgroundImage
表示 Region
不会基于图像计算其首选尺寸。这可能会或可能不会给您造成问题。例如,在布局的初始大小调整过程中,不会考虑图像。但是,此后,所有内容应与 ResizableImageView
一样工作-因为调整了 Region
的大小,因此图像也是如此。
A BackgroundImage
也可以通过CSS设置:
.your-region-class {
-fx-background-image:url(...);
-fx-background-repeat:不重复;
-fx-background-position:中心;
-fx-background-size:包含; / *或100%100%的行为就好像keepRatio为false * /
}
me and some friends are having a project, where we try to programm a game in JavaFX. We´ve got a GridPane, thats growing with ImageViews inside to hold the map and the game character, etc. (The game character and enemies will have their own imageview, that we can move around in the gridpane.) So, our problem now is, that we want out pictures to get bigger, when the window is getting bigger also, but right now only the columns of the GridPane are getting more distance to each other. I tried to find a way to change that, but I am not sure, if it is possible, cause ImageViews only have "FitHeight" and "FitWidth" and no prefWidth/Height or maxWidth/Height, as far as I see. I also tried to put HGrow and VGrow on always or sometimes, but it didn´t work. We can´t resize them with checking the stages size and changing their size in proportion to it all the time, cause we´ve got more than 800 ImageViews in our map to display all the Images. Here´s my code:
</image></ImageView>
<ImageView id="sample" fitHeight="25.0" fitWidth="27.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="15" GridPane.hgrow="ALWAYS" GridPane.rowIndex="24" GridPane.vgrow="ALWAYS">
<image>
<Image url="@sample.png" />
</image></ImageView>
One solution is to create a Region
subclass that simply wraps an ImageView
. This is better than binding the ImageView
's fit width/height properties to its parent because binding a child's dimensions to its parent's dimensions can cause issues with the layout system.
Here's an example:
import javafx.beans.DefaultProperty;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Region;
@DefaultProperty("image")
public class ResizableImageView extends Region {
/* *********************************************************************
* *
* Properties *
* *
***********************************************************************/
// -- image property
private final ObjectProperty<Image> image =
new SimpleObjectProperty<>(this, "image") {
@Override
protected void invalidated() {
imageView.setImage(get());
}
};
public final void setImage(Image image) {
this.image.set(image);
}
public final Image getImage() {
return image.get();
}
public final ObjectProperty<Image> imageProperty() {
return image;
}
// -- preserveRatio property
private final BooleanProperty preserveRatio =
new SimpleBooleanProperty(this, "preserveRatio") {
@Override
protected void invalidated() {
imageView.setPreserveRatio(get());
}
};
public final void setPreserveRatio(boolean preserveRatio) {
this.preserveRatio.set(preserveRatio);
}
public final boolean isPreserveRatio() {
return preserveRatio.get();
}
public final BooleanProperty preserveRatioProperty() {
return preserveRatio;
}
/* *********************************************************************
* *
* Instance Fields *
* *
***********************************************************************/
private final ImageView imageView = new ImageView();
/* *********************************************************************
* *
* Constructors *
* *
***********************************************************************/
public ResizableImageView() {
getStyleClass().add("resizable-image-view");
getChildren().add(imageView);
}
public ResizableImageView(Image image) {
this();
setImage(image);
}
/* *********************************************************************
* *
* Methods *
* *
***********************************************************************/
@Override
protected void layoutChildren() {
double x = snappedLeftInset();
double y = snappedTopInset();
double w = getWidth() - x - snappedRightInset();
double h = getHeight() - y - snappedRightInset();
imageView.setFitWidth(w);
imageView.setFitHeight(h);
positionInArea(imageView, x, y, w, h, -1, HPos.CENTER, VPos.CENTER);
}
@Override
protected double computePrefWidth(double height) {
double prefWidth = snappedLeftInset() + snappedRightInset();
var image = getImage();
if (image != null) {
double requestedWidth = image.getRequestedWidth();
prefWidth += (requestedWidth > 0.0 ? requestedWidth : image.getWidth());
}
return snapSizeX(prefWidth);
}
@Override
protected double computePrefHeight(double width) {
double prefHeight = snappedTopInset() + snappedBottomInset();
var image = getImage();
if (image != null) {
double requestedHeight = image.getRequestedHeight();
prefHeight += (requestedHeight > 0.0 ? requestedHeight : image.getHeight());
}
return snapSizeY(prefHeight);
}
}
You can set the minWidth
, minHeight
, maxWidth
, and maxHeight
properties to control how small or large the image can get.
You can accomplish nearly the same thing by using a BackgroundImage
.
var image = new Image(...);
var bgImage = new BackgroundImage(
image,
BackgroundRepeat.NO_REPEAT,
BackgroundRepeat.NO_REPEAT,
BackgroundPosition.CENTER,
new BackgroundSize(1.0, 1.0, true, true, false, false)
);
var region = new Region();
region.setBackground(new Background(bgImage));
This will cause the image to fill the entire Region
, same as if preserveRatio
was set to false
in the a ResizableImageView
example. If you want this to behave as if preserveRatio
was set to true
then use the following BackgroundSize
:
new BackgroundSize(1.0, 1.0, true, true, true, false);
The difference is the fifth argument, contain
, which has been changed from false
to true
. Check out the documentation to understand more about what each argument does.
Note that using a BackgroundImage
in this way means the Region
won't compute its preferred dimensions based on the image. This may or may not cause problems for you. For instance, during a layout's initial sizing it won't take the image into account. However, afterwards everything should work the same as ResizableImageView
—as the Region
is resized so is the image.
A BackgroundImage
can also be set via CSS:
.your-region-class {
-fx-background-image: url(...);
-fx-background-repeat: no-repeat;
-fx-background-position: center;
-fx-background-size: contain; /* or 100% 100% to act as if preserveRatio is false */
}
这篇关于是否可以使JavaFX中的ImageView响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!