Search code examples
javacssjavafxfxml

JavaFX Panes are not scaling accordingly


I am trying to make a board game in JavaFX for a school project. I have made a FXML based on the lowest possible resolution the game should be playable in (800x600). Although as soon as I make the resolution higher than it. Even 900x600 or 1920x1080 the scaling is about to fall off. enter image description here 800x600 resolution

enter image description here 1920x1080 resolution

The FXML code:

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

<?import java.net.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="600" minWidth="800" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.hsleiden.keesjes.controllers.GameController">
    <stylesheets>
        <URL value="@../../../game.css" />
    </stylesheets>
    <top>
        <BorderPane styleClass="header-section">
            <left>
                <Button onAction="#showHowToPlay" prefHeight="75.0" prefWidth="175.0" text="HOWTOPLAY" textAlignment="CENTER" />
            </left>
            <center><Label text="Keezen" /></center>
            <right>
                <HBox spacing="5">
                    <Button onAction="#pauseGame" prefHeight="75.0" prefWidth="175.0" text="PAUSE GAME" textAlignment="CENTER" />
                    <Button onAction="#switchToMenu" prefHeight="75.0" prefWidth="175.0" text="LEAVE GAME" textAlignment="CENTER" />
                </HBox>
            </right>
        </BorderPane>
    </top>
   <left>
      <BorderPane minHeight="505.0" minWidth="600.0" BorderPane.alignment="CENTER">
         <bottom>
            <FlowPane minHeight="105.0" minWidth="600.0" styleClass="cards" BorderPane.alignment="CENTER" />
         </bottom>
         <center>
            <Pane minHeight="400.0" minWidth="600.0" styleClass="game" BorderPane.alignment="CENTER" />
         </center>
      </BorderPane>
   </left>
   <right>
       <VBox minHeight="505.0" minWidth="200.0" BorderPane.alignment="CENTER">
           <Pane minHeight="200.0" minWidth="200.0" styleClass="players"/>
           <Pane minHeight="200.0" minWidth="200.0" styleClass="event"/>
           <Pane minHeight="105.0" minWidth="200.0" styleClass="chat"/>
       </VBox>
   </right>
</BorderPane>

And the related CSS code:

.root {
    -fx-font-size: 14px;
    -fx-background-color: #FFFFFF;
    -fx-font-family: "Roboto Light";
}
.header-section {
    -fx-padding: 10px;
    -fx-font-size: 20px;
    -fx-background-color: teal;
}
.header-section Label{
    -fx-text-fill: #FFFFFF;
    -fx-font-size: 200%;
    -fx-padding: 10px;
}
.game {
    -fx-background-color: lightgray;
}
.cards{
    -fx-background-color: lightgreen
}
.players{
    -fx-background-color: lightblue;
}
.event {
    -fx-background-color: yellow;
}
.chat{
    -fx-background-color: lime;
}

How would I go about maintaining Aspect Ratio's and stretch the pane accordingly to resolution? E.G. in a 1920x1080 Resolution the Light Gray should be 1280x720. In a 800x600 resolution it is 600x400. And everything in between.


Solution

  • So after a lot of searching I have managed to find an answer.

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import java.net.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.stage.Screen?>
    
    <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="600" minWidth="800" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.hsleiden.keesjes.controllers.GameController">
        <fx:define>
            <Screen fx:factory="getPrimary" fx:id="screen" />
        </fx:define>
        <stylesheets>
            <URL value="@../../../game.css" />
        </stylesheets>
        <top>
            <BorderPane styleClass="header-section">
                <left>
                    <Button onAction="#showHowToPlay" prefHeight="75.0" prefWidth="175.0" text="HOWTOPLAY" textAlignment="CENTER" />
                </left>
                <center><Label text="Keezen" /></center>
                <right>
                    <HBox spacing="5">
                        <Button onAction="#pauseGame" prefHeight="75.0" prefWidth="175.0" text="PAUSE GAME" textAlignment="CENTER" />
                        <Button onAction="#switchToMenu" prefHeight="75.0" prefWidth="175.0" text="LEAVE GAME" textAlignment="CENTER" />
                    </HBox>
                </right>
            </BorderPane>
        </top>
        <center>
           <BorderPane fx:id="game" prefHeight="${screen.visualBounds.height}" prefWidth="${screen.visualBounds.width}" BorderPane.alignment="CENTER">
               <center>
                   <BorderPane>
                       <center>
                           <Pane prefHeight="${game.height*0.8}" prefWidth="${game.width*0.8}" styleClass="game"/>
                       </center>
                       <bottom>
                           <Pane prefHeight="${game.height*0.2}" prefWidth="${game.width*0.8}" styleClass="cards" />
                       </bottom>
                   </BorderPane>
               </center>
               <right>
                   <VBox>
                       <Pane prefHeight="${game.height*0.4}" prefWidth="${game.width*0.2}" styleClass="players" />
                       <Pane prefHeight="${game.height*0.4}" prefWidth="${game.width*0.2}" styleClass="event" />
                       <Pane prefHeight="${game.height*0.2}" prefWidth="${game.width*0.2}" styleClass="chat" />
                   </VBox>
               </right>
           </BorderPane>
       </center>
    </BorderPane>
    

    What I ended up doing is defining the Screensize of the "Game" section. With this I could calculate different portions using percentage (floats) and align the items using border panes. I got what I was looking for.