调整图像大小以适应父节点

41

如何使ImageView中的图像自动调整大小,以便始终适合父节点?

这里是一个小代码示例:

@Override
public void start(Stage stage) throws Exception {
    BorderPane pane = new BorderPane();
    ImageView img = new ImageView("http://...");

    //didn't work for me:
    //img.fitWidthProperty().bind(new SimpleDoubleProperty(stage.getWidth())); 

    pane.setCenter(img);

    Scene scene = new Scene(pane);
    stage.setScene(scene);
    stage.show();
}

6个回答

66
@Override
public void start(Stage stage) throws Exception {
    BorderPane pane = new BorderPane();
    ImageView img = new ImageView("http://...");

    img.fitWidthProperty().bind(stage.widthProperty()); 

    pane.setCenter(img);

    Scene scene = new Scene(pane);
    stage.setScene(scene);
    stage.show();
}

3
JavaFX2 相对容易上手,但并非总是易于理解。一旦你熟悉了其中的概念,使用起来就像呼吸般自然。 - The Unfun Cat
13
真的吗?布局系统自己不能做到这一点吗?*facepalm* - Aleksandr Dubinsky
我曾经遇到过一个类似的问题,因为ImageView不会自动适应其父级容器。现在我需要一种方法来获取最大可用宽度和高度(我的布局更加复杂,所以简单地获取舞台或BorderPane的宽度不是一个选项)。我找到的最简单的解决方案是将ImageView包装在VBox中,默认情况下VBox可以适应其父级容器,并将ImageView的大小属性绑定到VBox的大小属性上(与上面的代码类似)。 - ComFreek
20
如何在FXML中进行设置? - Tomi
3
我选择:img.setPreserveRatio(true); img.fitWidthProperty().bind(stage.widthProperty()); img.fitHeightProperty().bind(stage.heightProperty()); - Steve Pitchers
真的吗?你是在告诉我FXML中没有办法做到这一点吗? - Yassir Khaldi

16

这是比绑定宽度属性更好的解决方案(更好,因为通常在将子元素绑定到其容器时,可能无法使容器变小。在其他情况下,容器甚至可能自动开始增长)。

以下解决方案依赖于覆盖 ImageView,以便我们可以让它表现为“可调整大小”,然后提供最小、首选和最大宽度/高度的实现。同样重要的是实际实现 resize() 调用。

class WrappedImageView extends ImageView
{
    WrappedImageView()
    {
        setPreserveRatio(false);
    }

    @Override
    public double minWidth(double height)
    {
        return 40;
    }

    @Override
    public double prefWidth(double height)
    {
        Image I=getImage();
        if (I==null) return minWidth(height);
        return I.getWidth();
    }

    @Override
    public double maxWidth(double height)
    {
        return 16384;
    }

    @Override
    public double minHeight(double width)
    {
        return 40;
    }

    @Override
    public double prefHeight(double width)
    {
        Image I=getImage();
        if (I==null) return minHeight(width);
        return I.getHeight();
    }

    @Override
    public double maxHeight(double width)
    {
        return 16384;
    }

    @Override
    public boolean isResizable()
    {
        return true;
    }

    @Override
    public void resize(double width, double height)
    {
        setFitWidth(width);
        setFitHeight(height);
    }
}

谢谢,那真的很有帮助。 - olivierr91
对于像我这样也想要居中的人,请看这里https://dev59.com/I4_ea4cB1Zd3GeqPO3tW;使用setTranslateX setTranslateY而不是setX setY,在resize方法中调用center。 - BWC semaJ
我该如何在 @FXML 文件中使用这个? - Carrein

5
使用ScrollPane或者简单的Pane可以解决这个问题: 示例:
 img_view1.fitWidthProperty().bind(scrollpane_imageview1.widthProperty()); 
 img_view1.fitHeightProperty().bind(scrollpane_imageview1.heightProperty());

6
我该如何在FXML中设置它? - Tomi
不起作用。如果我调整窗口大小,面板的宽度和高度保持不变,因此图像视图也是如此。 - T3rm1

1

这是一种计算宽度的方法,可以去除滚动条的宽度。

first:
myImageView.setPreserveRatio(true);

监测滚动条宽度的变化:

scrollPane.widthProperty().addListener((observable, oldValue, newValue) -> {
            myImageView.setFitWidth(newValue.doubleValue() - (oldValue.doubleValue() - scrollPane.getViewportBounds().getWidth()));
        });

滚动条宽度:
oldValue.doubleValue() - scrollPane.getViewportBounds().getWidth()

如何设置初始宽度?
primaryStage.show(); 之后

myImageView.setFitWidth(scrollPane.getViewportBounds().getWidth());


1
如果您希望ImageView适应窗口框架,请使用以下代码行:imageView.fitWidthProperty().bind(scene.widthProperty())。 请注意,我使用的是场景的widthProperty而不是舞台的。 示例:
import java.io.FileNotFoundException;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;

public class MapViewer extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws FileNotFoundException {
        String strTitle = "Titulo de la Ventana";
        int w_width = 800;
        int w_height = 412;
        primaryStage.setTitle(strTitle);
        primaryStage.setWidth(w_width);
        primaryStage.setHeight(w_height);

        Group root = new Group();
        Scene scene = new Scene(root);

        final ImageView imv = new ImageView("file:C:/Users/utp/Documents/1.2008.png");
        imv.fitWidthProperty().bind(scene.widthProperty());
        imv.setPreserveRatio(true);

        root.getChildren().add(imv);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

}

主舞台(primaryStage)的宽高比应与图像(1.2008.png)相似。


0

将父元素填充为纵横比,这可以解决当父元素的高度和宽度不符合比例时出现的问题,就像图片一样。

Image image = new Image(getClass().getResource(%path%).toString());
double ratio = image.getWidth() / image.getHeight();
double width = stage.getScene().getWidth();

ImageView imageView.setImage(image);
imageView.setFitWidth(width);
imageView.setFitHeight(width/ratio);
imageView.setPreserveRatio(true);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接