Custom Start Screen

Hi all,

I was wondering if it’s possible to add or remove menus from the start screen. By the start screen, I mean the screen that appears when the application first opens. I want to add a graphics menu option so that I can set custom presets in my game. Is this possible?


What you mean is refered to as the StartDialog / AppSettings.
I think per default you can only change the splash screen of it, but it should also possible by overriding the correct values and then returning a regular awt panel/swing jPanel/Frame whatever that is, just examine the code a bit and tell us if you’re having problems there.

Oh and you should probably use the AppSettings class there as that’s what is used by jme as well.

As-is you can mostly only tweak the image and the title text. It’s way easier to just make your own launcher in JavaFX or Swing though, since you can also avoid many other problems and issues that the default launcher has. Like not detecting refresh rate on iOS for example. It’s generally a poorly made placeholder.

Yep, it falls into the same category as FlyCam and simpleUpdate()… ie: the first things you will replace when you make a real game.

Does something like this work:

* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
package util.settings;

import com.jme3.system.AppSettings;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FXSettingsDialog extends Application {

        public boolean canStart = false;
        public boolean isCancelled = false;

        public VBox main;
        public List<HBox> horizontals;
        public Group userGroup;

        public StackPane root;

        public Map<Dimension, Dimension> dimensions;

        public String title = "Game";
        public Image image;

        public List<CheckBox> checkboxes;
        public List<ComboBox> dropdowns;

        public com.jme3.system.AppSettings appSettings;

        public Map<Object, Object> customSettings;

        public FXSettingsDialog(String[] args) {
                this(args, null);

        public FXSettingsDialog(String[] args, Group userDefined) {
                this.userGroup = userDefined;

    public void start(Stage primaryStage) {
        dimensions = new HashMap<>();

        //Put width and height dimensions
        //720p to 480p
        dimensions.put(new Dimension(1280, 720), new Dimension(640, 480));
        dimensions.put(new Dimension(1024, 768), new Dimension(640, 480));
        dimensions.put(new Dimension(1024, 1024), new Dimension(640, 480));

        //1080p to 720p
        dimensions.put(new Dimension(1440, 900), new Dimension(1280, 720));
        dimensions.put(new Dimension(1680, 1050), new Dimension(1280, 720));
        dimensions.put(new Dimension(1920, 1080), new Dimension(1280, 720));
        dimensions.put(new Dimension(1920, 1200), new Dimension(1280, 720));

        //1440p to 1080p
        dimensions.put(new Dimension(2376, 1824), new Dimension(1920, 1080));
        dimensions.put(new Dimension(2560, 1440), new Dimension(1920, 1080));
        dimensions.put(new Dimension(2560, 1440), new Dimension(1920, 1080));
        dimensions.put(new Dimension(2048, 1920), new Dimension(1920, 1080));
        dimensions.put(new Dimension(7680, 4320), new Dimension(3840, 2160));

                //4K to 1440p
        dimensions.put(new Dimension(3840, 2160), new Dimension(2560, 1440));

        root = new StackPane();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

        primaryStage.setScene(new Scene(root, dimensions.get(screenSize).getWidth(), dimensions.get(screenSize).getHeight()));

        appSettings = new AppSettings(true);
        customSettings = new HashMap<>();

        //User has not defined an alternate UI, loading defaults
        if(userGroup == null) {
                main = new VBox();
                horizontals = new ArrayList<>();


                ImageView imageView = new ImageView(image);

                        checkboxes = new ArrayList<>();
                        checkboxes.add(new ActionCheckBox("Fullscreen", 
                                new EventHandler<ActionEvent> (){
                                    public void handle(ActionEvent e){
                                        appSettings.put("Fullscreen", !(Boolean)appSettings.get("Fullscreen"));
                        checkboxes.add(new ActionCheckBox("V-Sync (Reduces Screen Tearing)", 
                        new EventHandler<ActionEvent> (){
                                    public void handle(ActionEvent e){
                                        appSettings.put("vsync", !(Boolean)appSettings.get("vsync"));
                        checkboxes.add(new ActionCheckBox("Gamma Correction (Makes Colors More Accurate)", 
                                new EventHandler<ActionEvent> (){
                                    public void handle(ActionEvent e){
                                        appSettings.put("gamma", !(Boolean)appSettings.get("gamma"));

                        HBox checkboxHBox = new HBox();

                        dropdowns = new ArrayList<>();
                        dropdowns.add(new ActionComboBox<Dimension>(dimensions.keySet(), new Action(){
                            public void onAction(Object object){
                                Dimension d = (Dimension) object;
                                appSettings.put("width", d.getWidth());
                                appSettings.put("height", d.getHeight());
                        dropdowns.add(new ActionComboBox<String>(Arrays.asList("30", "60", "120"), new Action(){
                            public void onAction(Object e){
                                appSettings.put("refreshrate", Integer.parseInt((String)e));
                        dropdowns.add(new ActionComboBox<String>(Arrays.asList("16", "24", "32"), new Action(){
                            public void onAction(Object e){
                                appSettings.put("colorbit", Integer.parseInt((String)e));

                        dropdowns.add(new ActionComboBox<String>(Arrays.asList("0", "4", "8", "16"), new Action(){
                            public void onAction(Object e){
                                appSettings.put("antialias", Integer.parseInt((String)e));

                        HBox dropbox = new HBox();



                HBox buttons = new HBox();

                Button start = new Button("Start");
                start.setOnAction(new EventHandler<ActionEvent>(){
                    public void handle(ActionEvent e){
                        canStart = true;

                Button cancel = new Button("Cancel");
                start.setOnAction(new EventHandler<ActionEvent>(){
                    public void handle(ActionEvent e){
                        isCancelled = true;


    public static class ActionCheckBox extends CheckBox {
        public ActionCheckBox(String label, EventHandler<ActionEvent> onAction) {

    public static class ActionComboBox<T> extends ComboBox<T> {

        public Action action;

        public ActionComboBox(Collection<T> options, Action onAction) {
                this.action = onAction;
                this.valueProperty().addListener(new ChangeListener<T>() {
                        public void changed(ObservableValue<? extends T> ov, T t, T t1) {


    public static interface Action {
        public abstract void onAction(Object object);

Like fallout or whatever. A separate application that gathers settings and launches the main game. You should probably pass the data as command line args to the game so you can keep them separate. Additionally you have the benefit of bypassing the launcher and creating an icon with args. Simple things make life simple :wink:

1 Like

Why does a settings dialog extend application? How many applications do you want in your application?

1 Like

That’s for JavaFX.

That’s not the issue @pspeed is saying: why are you making your settings dialog a JMonkey Application?

It’s not a jMonkey application. It’s a JavaFX application.

My import:

import javafx.application.Application;

Oracle’s tutorial:

1 Like

Yeah, it’s not… I didn’t read too deeply before commenting. I just get triggered by “extends Application”.

The JavaFx construct is still pretty weird but that’s not really OP’s fault. All of the good Java designers left after Oracle bought Java, I guess.

1 Like