JavaFX - 居中BackgroundImage覆盖BorderPane
我试图设置BackgroundImage
作为背景BorderPane
(pane
)在JavaFX。我想BackgroundImage
涵盖BorderPane
,它总是位于中心。我想用与background-image一样的CSS(for web)。JavaFX - 居中BackgroundImage覆盖BorderPane
我已经尝试:
-
使用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); } }
-
使用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); } }
Currentlly的代码(InlineCSS,ExternalCSS和OnlyJavaFX)所有版本产生导致这样的:
这里是CSS和HTML代码相同的例子。这是我希望它看起来像:
编辑1:
我意识到我已经发布了旧版本的代码,所以我会更新它。 (代码唯一的变化是,现在它的工作即使没有图像和CSS文件保存在计算机上,而是计划将在网上得到它。)
编辑2 Jose Martinez'sanswer后:
我已经测试你的代码,但它不起作用。 (我甚至在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);
}
}
的问题是,当你启动程序的代码只能
只要你调整大小(应用程序)窗口它不再居中。
我将不使用的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);
}
}
我试过你的代码,但它没有做我想做的事。请参阅我的问题中的编辑。 – ands
你必须重新计算窗口的大小。将居中代码移动到它自己的方法中。然后在调整大小时添加屏幕回调。在这个回调刷新翻译在背景ImageView .. –
这些行'scene.heightProperty()。addListener(windowHeightResized);''和'scene.widthProperty()。addListener(windowWidthResized);'不工作,它可能会用'windowResized()'做一些事情。我会自己修复它,但我不明白你想用那部分做什么。 – ands
更新了我的答案来处理窗口调整大小。 –