【问题标题】:How to set image, in ImageView fitting parent, without inflating parent如何在 ImageView 中设置图像适合父级,而不会使父级膨胀
【发布时间】:2021-06-27 12:14:59
【问题描述】:

我是这里的新成员,并且是 Javafx 的初学者,所以如果我的问题没有得到很好的解释,首先很抱歉。我重新编辑了我的问题,试图澄清我的观点,给出一个你可以从你身边执行的最小代码。所以这是我的问题: 我正在为 ImageView 组件和 ImageView 中设置的图像而苦苦挣扎。要点是,当我在 ImageView 中设置图像时,我失去了对周围窗格几何形状的控制。如果我执行相同的代码而不在 ImageView 中设置图像,则每个窗格的大小都会尊重我的设置。为了澄清我的观点,这是我从我这边测试过的最小代码,并且有效。

在下面的代码中,我将注释控制器中的行

imgView.setImage(image);

因为没有这条线显示的窗口给出了我期望的关于我的设置的良好几何形状。

所以这里是完整的代码:

FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>

<AnchorPane fx:id="anchorPane" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainViewController">
    <children>

     <VBox fx:id="parentVbox" spacing="0">
            <children>
                <HBox fx:id="topHbox">
                </HBox>

                <HBox fx:id="downHbox" alignment="CENTER_LEFT" spacing="0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">

                    <VBox fx:id="emptyVboxLeft" spacing="0">
                    </VBox>

                    <VBox fx:id="emptyVboxCentral" spacing="0">
                    </VBox>

                    <VBox fx:id="imgVboxRight" spacing="0">
                        <GridPane fx:id = "imgGp" >
                            <VBox fx:id="imgVbox" alignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="1">
                                <HBox fx:id = "imgHbox">
                                    <ImageView fx:id="imgView"/>
                                </HBox>
                            </VBox>
                        </GridPane>

                    </VBox>

                </HBox>
            </children>
        </VBox>



    </children>
    <padding>
        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
    </padding>
</AnchorPane>

主要:

package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.File;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{

        Parent root = FXMLLoader.load(new File("src/sample/MainView.fxml").toURI().toURL());
        primaryStage.setTitle("my issue");
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }


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

控制器:

package sample;

import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.layout.*;
import java.awt.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;



public class MainViewController {

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PANE * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * */
    @FXML
    public AnchorPane anchorPane;
    @FXML
    public VBox parentVbox;
    @FXML
    public HBox topHbox;
    @FXML
    public HBox downHbox;
    @FXML
    public VBox emptyVboxLeft; 
    @FXML
    public VBox emptyVboxCentral; 
    @FXML
    public VBox imgVboxRight; 




    @FXML
    public GridPane imgGp;
    @FXML
    public VBox imgVbox;
    @FXML
    public HBox imgHbox;

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * COMPONENTS * * * * * * * * * * * * * * * * * * * * * * * * * * *  * */
    //Components of Vbox Right
    @FXML public ImageView imgView;


    // geometrical parameters used for resizing
    public final double resizeWidthStageVsScreenSize = 0.5;
    public final double resizeHeightStageVsScreenSize = 0.5;
    public final double sizeVboxVsAnchorPane = 1.0;
    public final double divideValueHboxTopMenuVsVbox = 10.0; 
    public final double divideValueCorpusHboxVsVbox = 10.0/9; 
    public final double divideValueCorpusVboxLeftVsCorpusHbox = 10.0/2;
    public final double divideValueCorpusVboxCentralVsCorpusHbox = 10.0/5; 
    public final double divideValueCorpusVboxRightVsCorpusHbox = 10.0/3;

  /* * * * * * * * * * * * * * * * * * geometrical parameters related to and around the image * * * * * * * * * * * * * * * * * * */
    public final double percentBorderRowImgGp = 100.0/5;
    public final double percentBorderColumnImgGp = 100.0/3;
    public final double divideValueHeightCorpusHboxImgVsCorpusVboxImg = 10.0/8;



    public void initialize() throws FileNotFoundException {

        /* * * * * * * * * * * * * * * * Initialization of the window size * * * * * * * * * * * * * * * * * * */
        Dimension resolution = Toolkit.getDefaultToolkit().getScreenSize();
        double width = resolution.getWidth();
        double height = resolution.getHeight();
        double w = width*resizeWidthStageVsScreenSize;  // your window width
        double h = height*resizeHeightStageVsScreenSize;  // your window height
        //Window size preference when app is launched
        anchorPane.setPrefWidth(w);
        anchorPane.setPrefHeight(h);

        
        /* * * * * * * * * * * * Initialization of the geometry * * * * * * * * * * * * * * */
        //The parentVbox shall have the size of the anchor pane
        parentVbox.prefWidthProperty().bind(anchorPane.widthProperty());
        parentVbox.prefHeightProperty().bind(Bindings.divide(anchorPane.heightProperty(), sizeVboxVsAnchorPane));

        //Disposition de la hbox menu relative à la vbox
        topHbox.prefHeightProperty().bind(Bindings.divide(parentVbox.heightProperty(), divideValueHboxTopMenuVsVbox));

        //disposition de la corpus hbox relative à la vbox
        downHbox.prefHeightProperty().bind(Bindings.divide(parentVbox.heightProperty(), divideValueCorpusHboxVsVbox));
        //@CLUES
        downHbox.setStyle("-fx-background-color: #ADD8E6;"); //couleur bleue
        //disposition des 3 vbox relatives à la hbox
        emptyVboxLeft.prefWidthProperty().bind(Bindings.divide(downHbox.widthProperty(), divideValueCorpusVboxLeftVsCorpusHbox));
        //@CLUES
        emptyVboxLeft.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");
        emptyVboxCentral.prefWidthProperty().bind(Bindings.divide(downHbox.widthProperty(), divideValueCorpusVboxCentralVsCorpusHbox));
        //@CLUES
        emptyVboxCentral.setStyle("-fx-padding: 0;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 10 10 5 5;" +
                "-fx-border-color: blue;");
        imgVboxRight.prefWidthProperty().bind(Bindings.divide(downHbox.widthProperty(), divideValueCorpusVboxRightVsCorpusHbox));
        //@CLUES
        imgVboxRight.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");


        /* * * * * * * * * * * * Initialisation de la disposition des composants internes * * * * * * * * * * * * * * */

        //Initialisation des images de couvertures sur la Vbox Right

        //Sizing auto du gridPane de la Vbox right :
        imgGp.prefWidthProperty().bind(Bindings.divide(imgVboxRight.widthProperty(), 1.0));
        imgGp.prefHeightProperty().bind(Bindings.divide(imgVboxRight.heightProperty(), 1.0));
        final int numCols = 3 ;
        final int numRows = 3 ;
        for (int i = 0; i < numCols; i++) {
            ColumnConstraints colConst = new ColumnConstraints();
            if(i==0||i==2) {
                colConst.setPercentWidth(percentBorderColumnImgGp);
            }
            else
            {
                colConst.setPercentWidth(100.0-2* percentBorderColumnImgGp);
            }
            imgGp.getColumnConstraints().add(colConst);
        }
        for (int i = 0; i < numRows; i++) {
            RowConstraints rowConst = new RowConstraints();
            if(i==0||i==2) {
                rowConst.setPercentHeight(percentBorderRowImgGp);
            }
            else
            {
                rowConst.setPercentHeight(100.0-2* percentBorderRowImgGp);
            }
            imgGp.getRowConstraints().add(rowConst);

        }
        //@CLUES
        imgGp.setGridLinesVisible(true);


        //Sizing the Hbox containing the img regarding the Vbox img in the grid pane :
        imgHbox.prefHeightProperty().bind(Bindings.divide(imgVbox.heightProperty(), divideValueHeightCorpusHboxImgVsCorpusVboxImg));
        //@CLUES
        imgHbox.setStyle(
                        "-fx-border-color: coral;");

        //creating the image object
        InputStream stream = new FileInputStream("F:\\Documents\\resources\\bibliotheque\\cover.jpg");
        Image image = new Image(stream);
        //Setting image to the image view
        //imgView.setImage(image);
        imgView.setStyle("-fx-background-color: #FFFF00;");
        imgView.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: green;");
        //Setting the image view parameters
       imgView.fitWidthProperty().bind(imgHbox.widthProperty().multiply(0.5)); 
      imgView.fitHeightProperty().bind(imgHbox.heightProperty().multiply(0.5));

imgVbox.setStyle("-fx-background-color: #FFFF00;");



    }


}

所以现在请取消注释控制器的行并添加您自己的图像路径(在控制器中搜索“FileInputStream(”并添加您自己的路径)并取消注释行 imgView.setImage(image))。

您可能会看到,只在 ImageView 中添加图像,整个几何图形都被打乱了。

问题 1:为什么?如何解决这个问题?

问题 2:在控制器的最后几行中,我想将 imgView 绑定到其父 Hbox,例如使用 fitWidthProperty() 等将 imgView 设置为 Hbox 大小的一半...如您所见在代码中。我无法直接看到 imgView 组件(我尝试对其进行 setStyle 但没有给出任何内容..),但我可以看到图像占据了图像视图的一半。但我不明白这个控件,因为如果你在绑定到 Hbox 时将 fitWidthProperty 或 HeightProperty 设置为 1.0 或 0.99,你可能会看到视图正在扩展 => 为什么以及如何告诉我希望我的 imageView 必须设置为适合 Hbox 吗?

如果有人能帮我解决这个问题,我将不胜感激。

非常感谢您

【问题讨论】:

  • minimal reproducible example 请(包括应用程序、控制器、fxml).. 并遵守 java 命名约定(顺便说一句:很确定这个问题已经被问过 并且 之前回答过 - 你可能会通过一些研究找到它:)
  • 一般来说,将 PreserveRatio 设置为“true”并同时绑定 fitHeight 和 fitWidth 属性会很奇怪。仅绑定一个或另一个维度。使用subtract() 将图像缩放绑定到容器的宽度而不考虑容器中的填充通常最终导致容器增长以适应填充,从而导致图像增长,等等。最后,您在 VBox 内的 GridPane 内的 VBox 内有一个 HBox - 每个容器内部只有一个元素。你都需要它们吗?你确定可以抛弃 VBoxes 吗?
  • 旁注:使用javafx.stage.Screen 通过JavaFX API 获取屏幕尺寸。
  • @kleopatra 感谢您的建议。我试图提供一个最小的可复制示例。希望这将有助于更好地理解我的问题。提前致谢

标签: java javafx imageview


【解决方案1】:

调整窗口大小时可以在舞台上添加监听器

   primaryStage.heightProperty().addListener((obs, oldVal, newVal) -> {
        bookOfCorpusImgView.setFitHeight(primaryStage.getHeight());
        bookOfCorpusImgView.setFitWidth(primaryStage.getWidth());
   });

    primaryStage.widthProperty().addListener((obs, oldVal, newVal) -> {
        bookOfCorpusImgView.setFitHeight(primaryStage.getHeight());
        bookOfCorpusImgView.setFitWidth(primaryStage.getWidth());
   });

当然,您可以将新的高度/宽度编辑为您想要的任何亲戚,例如 primaryStage.getHeight()/3

【讨论】:

    猜你喜欢
    • 2012-07-15
    • 2014-11-12
    • 2019-11-10
    • 1970-01-01
    • 2013-07-08
    • 2017-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多