我在 BorderPane 的中心有一个 ImageView。左右是两个按钮。 BorderPnae 位于分割窗格内。我将 ImageView 的大小绑定到 BorderPane,如下所示:
imageView.fitHeightProperty().bind(borderPane.heightProperty());
imageView.fitWidthProperty().bind(borderPane.widthProperty());
imageView.setManaged(false);
当 setManaged 为 false 时,它会调整大小,但图像不在中心。如果我删除这条线,图像的中心就会很好。 这是一个mwe:
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
SplitPane root = new SplitPane();
BorderPane borderPane = new BorderPane();
ImageView imageView = new ImageView();
VBox placeHolder = new VBox();
imageView.fitHeightProperty().bind(borderPane.heightProperty());
imageView.fitWidthProperty().bind(borderPane.widthProperty());
imageView.setManaged(false);
borderPane.setCenter(imageView);
imageView.setImage(new Image("pathToImage"));
root.getItems().addAll(borderPane,placeHolder);
Scene scene = new Scene(root,700,700);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
我正在寻找一种将两者存档的方法。我尝试使用 Hbox 作为按钮和图像视图的容器,但这也禁用了大小调整。
将节点的尺寸绑定到其父级的尺寸通常会导致布局期间出现问题。更具体地说,它往往会阻止父级正确调整大小。创建“可调整大小的图像视图”的最可靠方法是创建自定义布局并覆盖
layoutChildren()
以调整图像视图的大小。
这是一个非常简单的例子:
import javafx.beans.property.ObjectProperty;
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;
public class ImageRegion extends Region {
private final ObjectProperty<Image> image = new SimpleObjectProperty<>(this, "image") {
@Override protected void invalidated() { view.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; }
private final ImageView view = new ImageView();
public ImageRegion() {
getStyleClass().add("image-region");
view.setPreserveRatio(true);
getChildren().add(view);
}
public ImageRegion(Image image) {
this();
setImage(image);
}
public ImageRegion(String imageUrl) {
this(new Image(imageUrl));
}
@Override
protected void layoutChildren() {
if (getImage() == null) {
return;
}
// content area dimensions
double cx = getInsets().getLeft();
double cy = getInsets().getTop();
double cw = getWidth() - getInsets().getRight() - cx;
double ch = getHeight() - getInsets().getBottom() - cy;
// image dimensions
double iw = getImageWidth();
double ih = getImageHeight();
view.setFitWidth(cw < iw ? cw : 0);
view.setFitHeight(ch < ih ? ch : 0);
positionInArea(view, cx, cy, cw, ch, 0, HPos.CENTER, VPos.CENTER);
}
/*
* Ignore the Image and ImageView when computing the minimum width and
* height. This allows the ImageRegion to be sized smaller than the Image.
*
* Compute the preferred width and height based on the Image directly rather
* than the ImageView.
*
* The Region.computeMaxWidth and Region.computeMaxHeight methods both
* return Double.MAX_VALUE. We want the ImageRegion able to be sized
* larger than the Image, so there is no reason to override those methods.
*/
@Override
protected double computeMinWidth(double height) {
return getInsets().getLeft() + getInsets().getRight();
}
@Override
protected double computeMinHeight(double width) {
return getInsets().getTop() - getInsets().getBottom();
}
@Override
protected double computePrefWidth(double height) {
return getInsets().getLeft() + getInsets().getRight() + getImageWidth();
}
@Override
protected double computePrefHeight(double width) {
return getInsets().getTop() + getInsets().getBottom() + getImageHeight();
}
private double getImageWidth() {
var image = getImage();
return image == null ? 0 : image.getWidth();
}
private double getImageHeight() {
var image = getImage();
return image == null ? 0 : image.getHeight();
}
}
注意这个
ImageRegion
课程:
将保留图像的纵横比。
如果区域的内容区域小于图像,将使图像变小。
不会使图像变大。
layoutChildren()
逻辑以更好地适合您的用例。对上述类的一些可能的改进包括:
preserveRatio
属性来控制是否保留图像的宽高比。
alignment
属性,用于控制图像小于内容区域时的定位方式。
snapXXX
方法。