簡體   English   中英

如何在JavaFX中調整窗口大小時調整圖像大小

[英]How to resize an image when resizing the window in JavaFX

我想在用戶拖動主窗口時自動調整圖像大小。 那可能嗎?

我有以下代碼設置一定大小的窗口。 它還從外部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();

}

將解決方案應用於JavaFx圖像調整大小到您的示例代碼並調整窗口大小會為我產生不同的圖像大小。

sizedefaultsizeresize

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);
    }
}

基於評論的替代方法和額外信息

如果你必須做所有這些,那么它是JavaFX平台的一個弱點。 理想情況下,我希望在圖像上有一個可以設置的縮放屬性,以便它使用SceneGraph來確定它的大小。

上面提出的解決方案只是一個答案,還有其他可能。 可以通過將各種屬性綁定到父節點的寬度和高度,或者通過覆蓋父節點中的layoutChildren來使用場景圖。

相關屬性:

  • 有一個scale屬性可以應用於任何節點。
  • 節點還具有可應用Scale變換列表
  • ImageView具有fitWidth和fitHeight屬性(在其他答案中演示了這一點)。

我更喜歡區域子類方法到scale屬性或基於變換的方法,因為然后根據布局管理器自動調整圖像大小。 上面定義的ImageViewPane只是一個一次性定義類,可以根據需要重復使用,使用ImageView或ImageViewPane的實際應用程序代碼幾乎相同。

另一種可能的方法是使用Region子類(例如Pane),它具有已定義的CSS樣式類或id,然后將CSS中圖像定義為背景 CSS定義圖像的好處在於,您可以使用其他基於CSS的屬性來定義圖像的大小,縮放,定位和重復等內容。 如果需要,也可以通過編程方式設置背景,而不是通過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());
}

只需使用帶有背景圖像的普通窗格,這里需要css。

#titleImage{
    -fx-background-image: url("../img/logo.png");
    -fx-background-repeat: stretch; 
    -fx-background-position: center center;
}

您是想要調整實際圖像的大小 ,還是只是為了居中?

你可以試試這個: VBox.setVgrow(root, Priority.ALWAYS); 看看這是不是你想要的。

另外,請小心你的圖像,因為它是一個png圖像。 我對那里的重新調整大小(實際圖像或透明背景)有點懷疑。

我知道這已經過時了,但是像我這樣的人可能偶然發現了這一點,所以這是我的解決方案。 我假設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());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM