Javafx Binding字体属性与场景框架

时间:2016-02-13 20:00:52

标签: javafx fonts binding size fxml

我目前正在编写一个数独求解器/游戏应用程序。然而,我正在努力让我的应用程序根据使用绑定的容器大小来管理文本的大小。我正在使用一个场景框架来控制何时加载不同的FXML文件及其各自的控制器,然后向用户显示。

目标:我想要完成的是当显示选择级别FXML时我希望它能使得当网格窗格的大小发生变化时,网格窗格内的文本会变得更大/更小。 / p>

问题:我遇到的是当在场景中显示不同的FXML时,我找不到为任何给定控件绑定文本的方法。我已经尝试在控制器中使用initialize方法,但问题是场景框架在应用程序启动时加载并初始化所有FXML和控制器文件。

我的程序的运行顺序如下:

  1. 主菜单
  2. 难度选择
  3. 选择级别
  4. 播放屏幕
  5. 提前谢谢,因为这是我第一次在堆栈溢出时发布。

    这是我正在使用的相关代码:

    Main.java

    public class Main extends Application {
    
    public static String mainMenu = "Main Menu";
    public static String mainMenuFXML = "/FXML/MainMenu.fxml";
    public static String levelDifficulty = "Difficulty Selection";
    public static String levelDifficultyFXML = "/FXML/LevelDifficulty.fxml";
    public static String chooseLevel = "Level Selection";
    public static String chooseLevelFXML = "/FXML/ChooseLevel.fxml";
    public static String playScreen = "PLay Screen";
    public static String playScreenFXML = "/FXML/PlayScreen.fxml";
    
    //Global Variable to be accessed across all classes
    //To be used to determine which scenes are loaded in the HashMap and also which scene has been set
    public static SceneFramework mainController = new SceneFramework();
    
    @Override
    public void start(Stage primaryStage) throws Exception{
    
        //Only the main menu scene is needed to be loaded at the start
        mainController.loadScene(Main.mainMenu, Main.mainMenuFXML);
        mainController.setScene(Main.mainMenu);
    
        StackPane root = new StackPane();
        root.getChildren().addAll(mainController);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
    
        launch(args);
    }
    }
    

    SceneFramework.java

    package Controller;
    
    
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Node;
    import javafx.scene.Parent;
    import javafx.scene.layout.StackPane;
    
    import java.util.HashMap;
    
    public class SceneFramework extends StackPane{
    
        //Constructor for the class
        public SceneFramework(){
            //The keyword super, overrides methods from the superclass
            super();
        }
    
        //This HashMap is used to hold the screens(scenes) to be used within the application
        protected HashMap<String, Node> scenes = new HashMap<>();
    
        //Adds the selected scene to the HashMap
        public void addScene(String title, Node scene) {
            scenes.put(title, scene);
        }
    
        //Returns the Node with the specified title for use within application
        public Node getScene(String title) {
            return scenes.get(title);
        }
    
        //Removes the selected scene from the framework
        public boolean unloadScene(String title){
            if(scenes.remove(title) == null){
                System.out.println("Scene cannot be located or it doesn't exist");
                return false;
            } else{
                return true;
            }
        }
    
        public boolean loadScene(String title, String resource){
            //encase code segment in try for exception handling,
            // as resources are required to be found and then loaded into memory
            try{
                //Load FXML File
                FXMLLoader loadedFXMLFile = new FXMLLoader(getClass().getResource(resource));
    
                //Get Parent of scene
                Parent loadScene = loadedFXMLFile.load();
    
                //Get the Controller class of the parent
                SetSceneParent sceneController = (loadedFXMLFile.getController());
    
                //Method of making sure every scene knows who it's parent is
                sceneController.setSceneParent(this);
    
                //Add scene to HashMap
                addScene(title, loadScene);
                return true;
    
            }catch (Exception e){
                //If FXML resource can't be loaded then generate this
                System.out.println("Could't load FXML file");
                return false;
            }
        }
    
        //Method for showing scenes
        //If one scenes if wanting to be shown then it is added to the root
        //If multiple scenes are wanting to be loaded then the first scene is removed and the new scene is then displayed
        public boolean setScene(final String title){
            //Check to see if scene can be found
            if(scenes.get(title) != null) {
                if(!getChildren().isEmpty()){
    
                    getChildren().remove(0);
                    getChildren().add(0 ,scenes.get(title));
    
                }else{
                        getChildren().add(scenes.get(title));
                }
                return true;
            } else{
                System.out.println("Scene not located!!!");
                return false;
            }
        }
    }
    

    SetSceneParent.java

    package Controller;
    
    import Controller.SceneFramework;
    
    public interface SetSceneParent {
    
       void setSceneParent(SceneFramework sceneParent);
    }
    

    ChooseLevelController.java

    package Controller;
    
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.layout.GridPane;
    
    import java.net.URL;
    import java.util.ResourceBundle;
    
    public class ChooseLevelController implements Initializable, SetSceneParent {
    
        @FXML
        public Label lblLevelSelection, lblLevel1, lblLevel2, lblLevel3, lblLevel4, lblLevel5, lblLevel6, lblLevel7, lblLevel8, lblLevel9, lblLevel10; // Value injected by FXMLLoader
        public Button backButton;
        public GridPane gridPaneCenter;
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
    
            //Assert code is to be used in debugging making sure references to files and their elements are correct
            assert lblLevel1 != null : "fx:id=\"lblLevel1\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel2 != null : "fx:id=\"lblLevel2\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel3 != null : "fx:id=\"lblLevel3\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel4!= null : "fx:id=\"lblLevel4\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel5 != null : "fx:id=\"lblLevel5\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel6 != null : "fx:id=\"lblLevel6\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel7 != null : "fx:id=\"lblLevel7\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel8 != null : "fx:id=\"lblLevel8\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel9 != null : "fx:id=\"lblLevel9\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
            assert lblLevel10 != null : "fx:id=\"lblLevel10\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
    
        }
    
        @Override
        public void setSceneParent(SceneFramework screenParent) {
            //Sets the parent of the scene by using the global variable of the class SceneFramework
            Main.mainController = screenParent;
        }
    
        //Logic code
        @FXML
        public void mouseClickedLevelLabel() {
    
            //Load the play screen when any Label is pressed
            lblLevel1.setOnMouseClicked(e -> handleLabelClick(1));
            lblLevel2.setOnMouseClicked(e -> handleLabelClick(2));
            lblLevel3.setOnMouseClicked(e -> handleLabelClick(3));
            lblLevel4.setOnMouseClicked(e -> handleLabelClick(4));
            lblLevel5.setOnMouseClicked(e -> handleLabelClick(5));
            lblLevel6.setOnMouseClicked(e -> handleLabelClick(6));
            lblLevel7.setOnMouseClicked(e -> handleLabelClick(7));
            lblLevel8.setOnMouseClicked(e -> handleLabelClick(8));
            lblLevel9.setOnMouseClicked(e -> handleLabelClick(9));
            lblLevel10.setOnMouseClicked(e -> handleLabelClick(10));
        }
    
        @FXML
        public void handleBackButtonAction() {
            //On clicking of the back button
            //The user is taken to the level difficulty scene
    
            Main.mainController.loadScene(Main.levelDifficulty, Main.levelDifficultyFXML);
            Main.mainController.setScene(Main.levelDifficulty);
            Main.mainController.unloadScene(Main.chooseLevel);
    
        }
    
        private void handleLabelClick(int levelSelected){
            SelectionStatus.setLevelStatus(levelSelected);
            Main.mainController.loadScene(Main.playScreen, Main.playScreenFXML);
            Main.mainController.setScene(Main.playScreen);
            Main.mainController.unloadScene(Main.chooseLevel);
        }
    
    
    
    }
    

    ChooseLevel.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.geometry.*?>
    <?import javafx.scene.text.*?>
    <?import javafx.scene.control.*?>
    <?import java.lang.*?>
    <?import javafx.scene.layout.*?>
    
    <BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller.ChooseLevelController">
       <center>
          <VBox alignment="CENTER" BorderPane.alignment="CENTER">
             <children>
                <GridPane fx:id="gridPaneCenter" alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1500.0" prefHeight="242.0" prefWidth="475.0" BorderPane.alignment="CENTER" VBox.vgrow="ALWAYS">
                  <columnConstraints>
                    <ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
                    <ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
                      <ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
                      <ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
                      <ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
                  </columnConstraints>
                  <rowConstraints>
                    <RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="137.0" vgrow="ALWAYS" />
                    <RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="138.0" vgrow="ALWAYS" />
                  </rowConstraints>
                   <children>
                      <Label fx:id="lblLevel1" onMousePressed="#mouseClickedLevelLabel" text="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel2" onMouseClicked="#mouseClickedLevelLabel" onMousePressed="#mouseClickedLevelLabel" text="2" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel3" onMousePressed="#mouseClickedLevelLabel" text="3" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel4" onMousePressed="#mouseClickedLevelLabel" text="4" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel5" onMousePressed="#mouseClickedLevelLabel" text="5" GridPane.columnIndex="4" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel6" onMouseClicked="#mouseClickedLevelLabel" onMousePressed="#mouseClickedLevelLabel" text="6" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel7" onMousePressed="#mouseClickedLevelLabel" text="7" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel8" onMousePressed="#mouseClickedLevelLabel" text="8" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel9" onMousePressed="#mouseClickedLevelLabel" text="9" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                      <Label fx:id="lblLevel10" onMousePressed="#mouseClickedLevelLabel" text="10" GridPane.columnIndex="4" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
                         <font>
                            <Font name="System Bold" size="36.0" />
                         </font>
                      </Label>
                   </children>
                </GridPane>
             </children>
          </VBox>
       </center>
       <top>
          <GridPane fx:id="gridPaneTop">
             <columnConstraints>
                <ColumnConstraints hgrow="ALWAYS" maxWidth="207.0" minWidth="10.0" prefWidth="20.0" />
                <ColumnConstraints hgrow="SOMETIMES" maxWidth="207.0" minWidth="10.0" prefWidth="58.0" />
                <ColumnConstraints hgrow="ALWAYS" maxWidth="207.0" minWidth="10.0" prefWidth="105.0" />
                <ColumnConstraints hgrow="ALWAYS" maxWidth="451.0" minWidth="10.0" prefWidth="418.0" />
             </columnConstraints>
             <rowConstraints>
                <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
             </rowConstraints>
             <children>
                <Button fx:id="backButton" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleBackButtonAction" prefHeight="30.0" prefWidth="0.0" text="Back" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.valignment="CENTER" />
                <Separator prefHeight="63.0" prefWidth="73.0" visible="false" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS" />
                <Label fx:id="lblLevelSelection" text="Level Selection" underline="true" GridPane.columnIndex="3">
                   <font>
                      <Font name="System Bold" size="36.0" />
                   </font>
                </Label>
                <Separator prefHeight="63.0" prefWidth="73.0" visible="false" />
             </children>
          </GridPane>
       </top>
       <bottom>
          <Region prefHeight="36.0" prefWidth="600.0" BorderPane.alignment="CENTER" />
       </bottom>
       <left>
          <HBox>
             <children>
                <Region maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="50.0" BorderPane.alignment="CENTER" HBox.hgrow="ALWAYS" />
             </children>
          </HBox>
       </left>
       <right>
          <HBox>
             <children>
                <Region maxWidth="1.7976931348623157E308" prefHeight="300.0" prefWidth="50.0" BorderPane.alignment="CENTER" HBox.hgrow="ALWAYS" />
             </children>
          </HBox>
       </right>
    </BorderPane>
    

1 个答案:

答案 0 :(得分:0)

试图运行您的代码,但失败了。我得到的只是一个白色的屏幕(在改变一些东西后让它运行并加载正确的fxml)。 我放弃了。

所以这是我的GUESS关于你想要完成的事情:

当您调整屏幕大小时,您希望字体大小随之缩放。

  • 向width属性添加侦听器
  • 在处理程序中,您使用窗口/窗格/对象/ w.e的更改宽度和高度。计算新的字体大小
  • 设置新字体大小

编辑:如果您发布了大量不能自行编译和运行的代码(如:最小示例),请至少指向代码的一部分,不工作 - 让人们更容易帮助你。现在你的问题是人们需要很长时间才能找到错误 - 这是大多数(如果不是全部)都不会做的事情;)

编辑2:您还可以在要扩展的标签/对象上使用.setScaleX(double).setScaleY(double) - 您无需更改字体大小。 (视用例而定)