2017-09-04 242 views
0

我試圖設置BackgroundImage作爲背景BorderPanepane)在JavaFX。我想BackgroundImage涵蓋BorderPane,它總是位於中心。我想用與background-image一樣的CSS(for web)。JavaFX - 居中BackgroundImage覆蓋BorderPane

我已經嘗試:

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

Currentlly的代碼(InlineCSSExternalCSSOnlyJavaFX)所有版本產生導致這樣的:

sample image

這裏是CSS和HTML代碼相同的例子。這是我希望它看起來像:

sample image

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

的問題是,當你啓動程序的代碼只能

sample image

只要你調整大小(應用程序)窗口它不再居中。

sample image

+0

更新了我的答案來處理窗口調整大小。 –

回答

1

我將不使用的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); 
    } 
} 
+0

我試過你的代碼,但它沒有做我想做的事。請參閱我的問題中的編輯。 – ands

+0

你必須重新計算窗口的大小。將居中代碼移動到它自己的方法中。然後在調整大小時添加屏幕回調。在這個回調刷新翻譯在背景ImageView .. –

+0

這些行'scene.heightProperty()。addListener(windowHeightResized);''和'scene.widthProperty()。addListener(windowWidthResized);'不工作,它可能會用'windowResized()'做一些事情。我會自己修復它,但我不明白你想用那部分做什麼。 – ands