Wednesday, March 18, 2015

JavaFX Toolbar Button Layout

For this simple post I will show how to layout your buttons on a JavaFX toolbar. There are many scenarios in which you would want to move these buttons around on the toolbar.  Therefore I will provide you a very simple example to accomplish left, right, center, and multiple alignments for your buttons.



The key to accomplishing this is using a <Pane HBox.hgrow="ALWAYS" /> between the edges to create space (see code below). Enjoy!!

This project has been uploaded to github. For the most recent updates please visit : https://github.com/dtbell99/JavaFXToolbar




FXML Code:
------------------


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

<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="364.0" prefWidth="727.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.broadlyapplicable.javafxexamples.toolbar.ToolbarExampleController">
   <children>
      <VBox prefHeight="577.0" prefWidth="727.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <Pane>
               <children>
                  <Label prefHeight="24.0" prefWidth="356.0" text="Left Aligned Buttons (Default)">
                     <font>
                        <Font size="19.0" />
                     </font>
                     <padding>
                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
                     </padding>
                  </Label>
               </children>
            </Pane>
             <ToolBar>
              <items>
                <Button mnemonicParsing="false" text="Left Button 1" />
                  <Button mnemonicParsing="false" text="Left Button 2" />
              </items>
            </ToolBar>
            <Pane>
               <children>
                  <Label prefHeight="24.0" prefWidth="356.0" text="Center Aligned Buttons">
                     <font>
                        <Font size="19.0" />
                     </font>
                     <padding>
                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
                     </padding>
                  </Label>
               </children>
            </Pane>
            <ToolBar>
              <items>
                  <Pane HBox.hgrow="ALWAYS" />
                <Button mnemonicParsing="false" text="Center Button 1" />
                  <Button mnemonicParsing="false" text="Center Button 2" />
                  <Pane HBox.hgrow="ALWAYS" />
              </items>
            </ToolBar>
            <Pane>
               <children>
                  <Label prefHeight="24.0" prefWidth="356.0" text="Right Aligned Buttons">
                     <font>
                        <Font size="19.0" />
                     </font>
                     <padding>
                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
                     </padding>
                  </Label>
               </children>
            </Pane>
            <ToolBar>
              <items>
                  <Pane HBox.hgrow="ALWAYS" />
                <Button mnemonicParsing="false" text="Right Button 1" />
                  <Button mnemonicParsing="false" text="Right Button 2" />
              </items>
            </ToolBar>
            <Pane>
               <children>
                  <Label prefHeight="24.0" prefWidth="356.0" text="Left Center Right Align Buttons">
                     <font>
                        <Font size="19.0" />
                     </font>
                     <padding>
                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
                     </padding>
                  </Label>
               </children>
            </Pane>
            <ToolBar>
               <items>
                  <Button mnemonicParsing="false" text="Left Button 1" />
                  <Button mnemonicParsing="false" text="Left Button 2" />
                  <Pane HBox.hgrow="ALWAYS" />
                  <Button mnemonicParsing="false" text="Left Button 1" />
                  <Button mnemonicParsing="false" text="Left Button 2" />
                  <Pane HBox.hgrow="ALWAYS" />
                  <Button mnemonicParsing="false" text="Left Button 1" />
                  <Button mnemonicParsing="false" text="Left Button 2" />
               </items>
            </ToolBar>
         </children>
      </VBox>
   </children>
</AnchorPane>

Thursday, March 5, 2015

JavaFX Capture & Restore Splitpane Divider Position

Here is another simple code example on how to capture, store, and recover the divider position of a JavaFX splitpane. Implementing this approach allows your splitpane divider to be persisted when you close your application and restored as you left it when you closed the window.

Once the application is built and run you can drag the divider and see the current value of the position. Upon closing the program and restarting the divider should return to its last position.


Concepts: This example demonstrates the following:

1) How to access the PositionProperty field on the splitpane divider and add a listener to capture change events using a lambda function in Java 8.

2) How to use the javafx.application.Platform.runLater method to set the divider position when your application launches. (This technique is necessary due to how the application starts up and initializes)

3) How to store and retrieve simple application preferences using java.util.prefs.Preferences.


Requirements: Java SE 8







package com.broadlyapplicable.javafxexamples;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.prefs.Preferences;
import javafx.beans.property.DoubleProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;

public class FXMLDocumentController implements Initializable {
 
    private static final String SPLIT_PANE_DIVIDER = "SplitPaneDivider";
    private static final String NODE = "FXMLDocumentController";
 
    @FXML
    private SplitPane splitPane;
 
    @FXML
    private Label dividerLabel;
 
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        javafx.application.Platform.runLater(new Runnable() {
            @Override
            public void run() {
                Preferences pref = Preferences.userRoot().node(NODE);
                double splitPaneDivider = pref.getDouble(SPLIT_PANE_DIVIDER, .25);
                splitPane.setDividerPositions(splitPaneDivider);
            }
        });
     
        DoubleProperty dividerPositionProperty = splitPane.getDividers().get(0).positionProperty();
        dividerPositionProperty.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
            dividerLabel.setText(newValue.toString());
            Preferences pref = Preferences.userRoot().node(NODE);
            pref.putDouble(SPLIT_PANE_DIVIDER, newValue.doubleValue());
        });
    }  
 
}




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

<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="427.0" prefWidth="570.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.broadlyapplicable.javafxexamples.FXMLDocumentController">
    <children>
      <VBox prefHeight="427.0" prefWidth="570.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <SplitPane fx:id="splitPane" dividerPositions="0.33098591549295775">
              <items>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" style="-fx-background-color: #dddddd;" />
                <AnchorPane prefHeight="425.0" prefWidth="86.0" style="-fx-background-color: #aaaaaa;" />
              </items>
            </SplitPane>
            <Label fx:id="dividerLabel" alignment="CENTER" text="0.0">
               <font>
                  <Font size="31.0" />
               </font>
               <padding>
                  <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
               </padding>
            </Label>
         </children>
      </VBox>
    </children>
</AnchorPane>