JavaFX - 居中覆盖 BorderPane 的 BackgroundImage

标签 java css javafx background-image borderpane

我正在尝试设置 BackgroundImage作为BorderPane的背景( pane ) 在 JavaFX 中。我想要那个BackgroundImage封面 BorderPane并且它始终位于中心。我想用 background-image 做与 CSS(用于网络)相同的事情.

我已经试过了:

  1. 使用 CSS (fx-CSS)

    package application;
    
    import javafx.application.Application;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.BorderPane;
    
    public class ExternalCSS extends Application {
        @Override
        public void start(Stage primaryStage) {
            try {
    
                //BorderPane()
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html
                BorderPane borderPane = new BorderPane();
    
    
                //Button(String text)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Button.html
                Button btn = new Button("Center");
    
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html#setCenter-javafx.scene.Node-
                borderPane.setCenter(btn);
    
    
                Scene scene = new Scene(borderPane, 600, 600);
    
                URL path = getClass().getResource("resources/BackgroundStyle.css");
    
                if(path != null) {
                    scene.getStylesheets().add(path.toExternalForm());
                } else {
                    scene.getStylesheets().add("https://raw.githubusercontent.com/4nds/CenteredBackgroundImage/master/Background/src/application/resources/BackgroundStyleExternalURL.css");
                }
    
                borderPane.setId("background_id");
    
                primaryStage.setScene(scene);
                primaryStage.show();
    
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    此代码使用外部 CSS(您可以找到我的 CSS 代码 here )或者您可以将下面的代码与内联 CSS 一起使用:

    package application;
    
    import javafx.application.Application;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.BorderPane;
    
    public class InlineCSS extends Application {
        @Override
        public void start(Stage primaryStage) {
            try {
    
                //BorderPane()
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html
                BorderPane borderPane = new BorderPane();
    
    
                //Button(String text)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Button.html
                Button btn = new Button("Center");
    
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html#setCenter-javafx.scene.Node-
                borderPane.setCenter(btn);
    
    
                Scene scene = new Scene(borderPane, 600, 600);
    
                URL path = getClass().getResource("resources/black_clock.png");
    
                String image = null;
                if(path != null) {
                    image = path.toExternalForm();
                } else {
                    image = "https://raw.githubusercontent.com/4nds/CenteredBackgroundImage/master/Background/src/application/resources/black_clock.png";
                }                   
    
                borderPane.setStyle("-fx-background-image: url('" + image + "'); " +
                           "-fx-background-position: center center; " +
                           "-fx-background-repeat: no-repeat;" +
                           "-fx-background-size: cover");
    
                primaryStage.setScene(scene);
                primaryStage.show();
    
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
  2. 仅使用 JavaFX:

    package application;
    
    
    import java.io.File;
    
    import javafx.application.Application;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.image.Image;
    import javafx.scene.layout.Background;
    import javafx.scene.layout.BackgroundImage;
    import javafx.scene.layout.BackgroundPosition;
    import javafx.scene.layout.BackgroundRepeat;
    import javafx.scene.layout.BackgroundSize;
    import javafx.scene.layout.BorderPane;
    
    
            public class OnlyJavaFX extends Application {
        @Override
        public void start(Stage primaryStage) {
            try {
    
                //BorderPane()
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html
                BorderPane borderPane = new BorderPane();
    
    
                //File(String pathname)
                //https://docs.oracle.com/javase/8/docs/api/java/io/File.html
                File file = new File("./src/application/resourcesa/black_clock.png");
    
                Image img = null;
                if(file.exists()) {
                    //Image(InputStream is)
                    //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html
                    img = new Image(file.getAbsoluteFile().toURI().toString());
                } else {
                    //Image(String url)
                    //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html
                    img = new Image("https://raw.githubusercontent.com/4nds/CenteredBackgroundImage/master/Background/src/application/resources/black_clock.png");
                }
    
                //BackgroundSize(double width, double height, boolean widthAsPercentage, boolean heightAsPercentage, boolean contain, boolean cover)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BackgroundSize.html
                BackgroundSize bgSize = new BackgroundSize(0, 0, false, false, false, true);
    
                //public BackgroundImage(Image image, BackgroundRepeat repeatX, BackgroundRepeat repeatY, BackgroundPosition position, BackgroundSize size)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BackgroundImage.html
                BackgroundImage bgImg = new BackgroundImage(img,
                        BackgroundRepeat.NO_REPEAT,
                        BackgroundRepeat.NO_REPEAT,
                        BackgroundPosition.CENTER,
                        bgSize);
    
                //Background(BackgroundImage... images)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/Background.html
                Background bg = new Background(bgImg);
    
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/Region.html#setBackground-javafx.scene.layout.Background-
                borderPane.setBackground(bg);
    
    
                //Button(String text)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Button.html
                Button btn = new Button("Center");
    
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html#setCenter-javafx.scene.Node-
                borderPane.setCenter(btn);
    
    
                Scene scene = new Scene(borderPane, 600, 600);
                primaryStage.setScene(scene);
                primaryStage.show();
    
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

目前所有版本的代码(InlineCSSExternalCSSOnlyJavaFX)都会产生如下结果:

sample image

这是同一示例的 CSS 和 HTML 代码。这就是我想要的样子:

sample image

编辑 1:

我意识到我已经发布了我的代码的旧版本,所以我会更新它。 (代码中唯一的变化是现在即使没有图像和 CSS 文件保存在您的计算机上它也可以工作,而是程序将在线获取它。)

Jose Martinez's之后编辑2 answer :

我已经测试了你的代码,但它不起作用。 (我什至在 Y 轴方向添加了背景 ImageView 的翻译,在你的回答中它只是在 X 轴方向,而且我已经设置了 borderPane 的大小以匹配场景(应用程序窗口)的大小但是它仍然不起作用)。这是完整的代码(与您的回答相同,但有一些我已经提到的小修复):

package application;


import java.io.File;

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;

public class Try1 extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {


            //BorderPane()
            //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html
            BorderPane borderPane = new BorderPane();

            //jot down the width and height of the scene
            double width = 600;
            double height = 600;

            //File(String pathname)
            //https://docs.oracle.com/javase/8/docs/api/java/io/File.html
            File file = new File("./src/application/resourcesa/black_clock.png");

            Image img = null;
            if(file.exists()) {
                //Image(InputStream is)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html
                img = new Image(file.getAbsoluteFile().toURI().toString());
            } else {
                //Image(String url)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html
                img = new Image("https://raw.githubusercontent.com/4nds/CenteredBackgroundImage/master/Background/src/application/resources/black_clock.png");
            }


            ImageView background = new ImageView(img);

            //..center the background
            double translateX = width/2 - img.getWidth()/2;
            System.out.println(translateX);
            background.setTranslateX(translateX);

            double translateY = height/2 - img.getHeight()/2;
            System.out.println(translateY);
            background.setTranslateY(translateY);

            //Button(String text)
            //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Button.html
            Button btn = new Button("Center");

            //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html#setCenter-javafx.scene.Node-
            borderPane.setCenter(btn);

            //make root with BorderPane and background image
            Group root = new Group (background, borderPane);

            Scene scene = new Scene(root, width, height);        

            primaryStage.setScene(scene);

            //this lines set borderPane's dimensions to be the same as scene
            borderPane.prefHeightProperty().bind(scene.heightProperty());
            borderPane.prefWidthProperty().bind(scene.widthProperty());

            primaryStage.show();

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

问题是这段代码只有在你启动程序时才有效

sample image

一旦您调整(应用程序)窗口的大小,它就不再居中。

sample image

最佳答案

我会通过不使用 BackGroundImage 来实现这一点,而是只使用另一个区域,其中可以包含背景 ImageView。然后平移背景 ImageView 以使其居中。

我调整了您的代码来做到这一点。我使用一个组作为场景的根节点。在该根目录中,我放置了背景的 ImageView 和 BorderPane。

        //BorderPane()
        //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html
        BorderPane borderPane = new BorderPane();

        //jot down the width and height of the scene
        double width = 600;
        double height = 600;

        //Image(InputStream is)
        //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html
        Image img = new Image(file.getAbsoluteFile().toURI().toString());
        ImageView background = new ImageView(img);
        //..center the background
        double translateX = width/2 - img.getWidth()/2;
        background.setTranslateX(translateX);

        //Button(String text)
        //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Button.html
        Button btn = new Button("Center");

        //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html#setCenter-javafx.scene.Node-
        borderPane.setCenter(btn);

        //make root with BorderPane and background image
        Group root = new Group (background, borderPane);

        Scene scene = new Scene(root, width, height);

编辑:处理调整大小

1) 将背景 ImageView 移动为对象字段。 2) 创建使背景 ImageView 居中的方法。 3)每当调整窗口大小时,创建回调以使背景ImageView居中。

public class Try1 extends Application {

    private ImageView background = new ImageView(img);

    private final ChangeListener<Number> windowWidthResized = (ObservableValue<? extends Number> ov, Number t, Number t1) -> {
    windowResized();
};

    private final ChangeListener<Number> windowHeightResized = (ObservableValue<? extends Number> ov, Number t, Number t1) -> {
    windowResized();
};

    private void windowResized(){
        double newHeight = scene.getHeight();
        double newWidth = scene.getWidth();
        centerBackgroundImage(newWidth, newHeight);
    }

    private void centerBackgroundImage(double width, double height) {
            double translateX = width/2 - img.getWidth()/2;
            System.out.println(translateX);
            background.setTranslateX(translateX);

            double translateY = height/2 - img.getHeight()/2;
            System.out.println(translateY);
            background.setTranslateY(translateY);
    }

    @Override
    public void start(Stage primaryStage) {
        try {


            //BorderPane()
            //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html
            BorderPane borderPane = new BorderPane();

            //jot down the width and height of the scene
            double width = 600;
            double height = 600;

            //File(String pathname)
            //https://docs.oracle.com/javase/8/docs/api/java/io/File.html
            File file = new File("./src/application/resourcesa/black_clock.png");

            Image img = null;
            if(file.exists()) {
                //Image(InputStream is)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html
                img = new Image(file.getAbsoluteFile().toURI().toString());
            } else {
                //Image(String url)
                //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html
                img = new Image("https://raw.githubusercontent.com/4nds/CenteredBackgroundImage/master/Background/src/application/resources/black_clock.png");
            }


            background.setImage(img);

            //..center the background
            centerBackgroundImage(width, height);

            //Button(String text)
            //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Button.html
            Button btn = new Button("Center");

            //https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/BorderPane.html#setCenter-javafx.scene.Node-
            borderPane.setCenter(btn);

            //make root with BorderPane and background image
            Group root = new Group (background, borderPane);

            Scene scene = new Scene(root, width, height);

            //add callbacks to handle window resize
            scene.heightProperty().addListener(windowResized);
            scene.widthProperty().addListener(windowWidthResized);        

            primaryStage.setScene(scene);

            //this lines set borderPane's dimensions to be the same as scene
            borderPane.prefHeightProperty().bind(scene.heightProperty());
            borderPane.prefWidthProperty().bind(scene.widthProperty());

            primaryStage.show();

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

关于JavaFX - 居中覆盖 BorderPane 的 BackgroundImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46043562/

相关文章:

java - 使用 Gluon ShareService 共享多个文件(图片和 txt)

JavaFX Beans 绑定(bind)突然停止工作

java - 如何在 Android 中递归扫描目录

java - 如何加速Java中的数组交集?

java - 如何在 Java 上 GZIP 文件并通过 OutputStream 发送

javascript - 隐藏div vanilla javascript的动态方式

javascript - jquery 从下拉菜单更改边框样式

java - JavaFX 中的 "automatic injection of location and resources properties into the controller"是什么?

java.sql.SQLException : ORA-06502: PL/SQL: numeric or value error: character to number conversio 异常

javascript - 如何删除elem和下一个弹窗?