|
@@ -1,10 +1,11 @@
|
|
= Interacting with the GUI from Java
|
|
= Interacting with the GUI from Java
|
|
-:author:
|
|
|
|
-:revnumber:
|
|
|
|
|
|
+:author:
|
|
|
|
+:revnumber:
|
|
:revdate: 2016/03/17 20:48
|
|
:revdate: 2016/03/17 20:48
|
|
:keywords: gui, documentation, input, control, hud, nifty
|
|
:keywords: gui, documentation, input, control, hud, nifty
|
|
:relfileprefix: ../../
|
|
:relfileprefix: ../../
|
|
:imagesdir: ../..
|
|
:imagesdir: ../..
|
|
|
|
+:experimental:
|
|
ifdef::env-github,env-browser[:outfilesuffix: .adoc]
|
|
ifdef::env-github,env-browser[:outfilesuffix: .adoc]
|
|
|
|
|
|
|
|
|
|
@@ -14,18 +15,18 @@ ifdef::env-github,env-browser[:outfilesuffix: .adoc]
|
|
. <<jme3/advanced/nifty_gui_overlay#,Nifty GUI Overlay>> or <<jme3/advanced/nifty_gui_projection#,Nifty GUI Projection>>
|
|
. <<jme3/advanced/nifty_gui_overlay#,Nifty GUI Overlay>> or <<jme3/advanced/nifty_gui_projection#,Nifty GUI Projection>>
|
|
. *Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ Java Interaction*
|
|
. *Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ Java Interaction*
|
|
|
|
|
|
-In the previous parts of the tutorial, you created a two-screen user interface. But it is still static, and when you click the buttons, nothing happens yet. The purpose of the +++<abbr title="Graphical User Interface">GUI</abbr>+++ is to communicate with your Java classes: Your game needs to know what the users clicked, which settings they chose, which values they entered into a field, etc. Similarly, the user needs to know what the currently game state is (score, health, etc).
|
|
|
|
|
|
+In the previous parts of the tutorial, you created a two-screen user interface. But it is still static, and when you click the buttons, nothing happens yet. The purpose of the +++<abbr title="Graphical User Interface">GUI</abbr>+++ is to communicate with your Java classes: Your game needs to know what the users clicked, which settings they chose, which values they entered into a field, etc. Similarly, the user needs to know what the currently game state is (score, health, etc).
|
|
|
|
|
|
|
|
|
|
== Connect GUI to Java Controller
|
|
== Connect GUI to Java Controller
|
|
|
|
|
|
To let a Nifty screen communicate with the Java application, you register a `ScreenController` to every NiftyGUI screen. You create a ScreenController by creating a Java class that implements the `de.lessvoid.nifty.screen.ScreenController` interface and its abstract methods.
|
|
To let a Nifty screen communicate with the Java application, you register a `ScreenController` to every NiftyGUI screen. You create a ScreenController by creating a Java class that implements the `de.lessvoid.nifty.screen.ScreenController` interface and its abstract methods.
|
|
|
|
|
|
-Create an AppState *MyStartScreen*.java file in your package. ( Rightclick on your package → New → Other… → JME3 Classes → New AppState)
|
|
|
|
|
|
+Create an AppState *MyStartScreen*.java file in your package. ( btn:[RMB] click on your package and select `menu:New[Other>JME3 Classes>New BaseAppState]`)
|
|
|
|
|
|
-*Pro Tip:* Since you are writing a jME3 application, you can additionally make the ScreenController class extend the <<jme3/advanced/application_states#,AbstractAppState>> class! This gives the ScreenController access to the application object and to the update loop!
|
|
|
|
|
|
+*Pro Tip:* Since you are writing a jME3 application, you can additionally make the ScreenController class extend the <<jme3/advanced/application_states#,BaseAppState>> class! This gives the ScreenController access to the application object and to the update loop!
|
|
|
|
|
|
-Now add *implements ScreenController* to _public class MyStartScreen extends AbstractAppState{_ and add *import de.lessvoid.nifty.screen.ScreenController;*
|
|
|
|
|
|
+Now add *implements ScreenController* to _public class MyStartScreen extends BaseAppState{_ and add *import de.lessvoid.nifty.screen.ScreenController;*
|
|
|
|
|
|
Continue with adding:
|
|
Continue with adding:
|
|
|
|
|
|
@@ -33,15 +34,15 @@ Continue with adding:
|
|
----
|
|
----
|
|
|
|
|
|
import de.lessvoid.nifty.screen.Screen;
|
|
import de.lessvoid.nifty.screen.Screen;
|
|
-
|
|
|
|
|
|
+
|
|
...
|
|
...
|
|
-
|
|
|
|
|
|
+
|
|
public void bind(Nifty nifty, Screen screen) {
|
|
public void bind(Nifty nifty, Screen screen) {
|
|
- throw new UnsupportedOperationException("Not supported yet.");
|
|
|
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
}
|
|
}
|
|
|
|
|
|
public void onStartScreen() {
|
|
public void onStartScreen() {
|
|
- throw new UnsupportedOperationException("Not supported yet.");
|
|
|
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
}
|
|
}
|
|
|
|
|
|
public void onEndScreen() {
|
|
public void onEndScreen() {
|
|
@@ -49,55 +50,82 @@ public void onEndScreen() {
|
|
}
|
|
}
|
|
|
|
|
|
----
|
|
----
|
|
-
|
|
|
|
|
|
+.Complete BaseAppState file
|
|
[source,java]
|
|
[source,java]
|
|
----
|
|
----
|
|
-/*
|
|
|
|
- * To change this template, choose Tools | Templates
|
|
|
|
- * and open the template in the editor.
|
|
|
|
- */
|
|
|
|
package mygame;
|
|
package mygame;
|
|
|
|
|
|
import com.jme3.app.Application;
|
|
import com.jme3.app.Application;
|
|
-import com.jme3.app.state.AbstractAppState;
|
|
|
|
-import com.jme3.app.state.AppStateManager;
|
|
|
|
|
|
+import com.jme3.app.state.BaseAppState;
|
|
import de.lessvoid.nifty.Nifty;
|
|
import de.lessvoid.nifty.Nifty;
|
|
import de.lessvoid.nifty.screen.Screen;
|
|
import de.lessvoid.nifty.screen.Screen;
|
|
import de.lessvoid.nifty.screen.ScreenController;
|
|
import de.lessvoid.nifty.screen.ScreenController;
|
|
|
|
|
|
-public class MyStartScreen extends AbstractAppState implements ScreenController {
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public void initialize(AppStateManager stateManager, Application app) {
|
|
|
|
- super.initialize(stateManager, app);
|
|
|
|
- //TODO: initialize your AppState, e.g. attach spatials to rootNode
|
|
|
|
- //this is called on the OpenGL thread after the AppState has been attached
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public void update(float tpf) {
|
|
|
|
- //TODO: implement behavior during runtime
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public void cleanup() {
|
|
|
|
- super.cleanup();
|
|
|
|
- //TODO: clean up what you initialized in the initialize method,
|
|
|
|
- //e.g. remove all spatials from rootNode
|
|
|
|
- //this is called on the OpenGL thread after the AppState has been detached
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void bind(Nifty nifty, Screen screen) {
|
|
|
|
- throw new UnsupportedOperationException("Not supported yet.");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void onStartScreen() {
|
|
|
|
- throw new UnsupportedOperationException("Not supported yet.");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void onEndScreen() {
|
|
|
|
- throw new UnsupportedOperationException("Not supported yet.");
|
|
|
|
- }
|
|
|
|
|
|
+public class MyStartScreen extends BaseAppState implements ScreenController {
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void initialize(Application app) {
|
|
|
|
+ //It is technically safe to do all initialization and cleanup in the
|
|
|
|
+ //onEnable()/onDisable() methods. Choosing to use initialize() and
|
|
|
|
+ //cleanup() for this is a matter of performance specifics for the
|
|
|
|
+ //implementor.
|
|
|
|
+ //TODO: initialize your AppState, e.g. attach spatials to rootNode
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void cleanup(Application app) {
|
|
|
|
+ //TODO: clean up what you initialized in the initialize method,
|
|
|
|
+ //e.g. remove all spatials from rootNode
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //onEnable()/onDisable() can be used for managing things that should
|
|
|
|
+ //only exist while the state is enabled. Prime examples would be scene
|
|
|
|
+ //graph attachment or input listener attachment.
|
|
|
|
+ @Override
|
|
|
|
+ protected void onEnable() {
|
|
|
|
+ //Called when the state is fully enabled, ie: is attached and
|
|
|
|
+ //isEnabled() is true or when the setEnabled() status changes after the
|
|
|
|
+ //state is attached.
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void onDisable() {
|
|
|
|
+ //Called when the state was previously enabled but is now disabled
|
|
|
|
+ //either because setEnabled(false) was called or the state is being
|
|
|
|
+ //cleaned up.
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void update(float tpf) {
|
|
|
|
+ //TODO: implement behavior during runtime
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Bind this ScreenController to a screen. This happens right before the
|
|
|
|
+ * onStartScreen STARTED and only exactly once for a screen!
|
|
|
|
+ * @param nifty nifty
|
|
|
|
+ * @param screen screen
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void bind(Nifty nifty, Screen screen) {
|
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * called right after the onStartScreen event ENDED.
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void onStartScreen() {
|
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * called right after the onEndScreen event ENDED.
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void onEndScreen() {
|
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
----
|
|
----
|
|
@@ -119,14 +147,15 @@ Or the same in a Java syntax, respectively:
|
|
|
|
|
|
[source,java]
|
|
[source,java]
|
|
----
|
|
----
|
|
-
|
|
|
|
- nifty.addScreen("start", new ScreenBuilder("start") {{
|
|
|
|
- controller(new mygame.MyStartScreen())}});
|
|
|
|
|
|
+nifty.addScreen("start", new ScreenBuilder("start") {{
|
|
|
|
+ controller(new mygame.MyStartScreen());
|
|
|
|
+}}.build(nifty));
|
|
|
|
|
|
----
|
|
----
|
|
|
|
|
|
Now the Java class `MyStartScreen` and this +++<abbr title="Graphical User Interface">GUI</abbr>+++ screen (`start`) are connected. For this example you can also connect the `hud` screen to MyStartScreen.
|
|
Now the Java class `MyStartScreen` and this +++<abbr title="Graphical User Interface">GUI</abbr>+++ screen (`start`) are connected. For this example you can also connect the `hud` screen to MyStartScreen.
|
|
|
|
|
|
|
|
+See also: link:https://versaweb.dl.sourceforge.net/project/nifty-gui/nifty-gui/1.3.2/nifty-gui-the-manual-1.3.2.pdf[Nifty GUI - the Manual: Elements (Screen Controller)]
|
|
|
|
|
|
== Make GUI and Java Interact
|
|
== Make GUI and Java Interact
|
|
|
|
|
|
@@ -139,34 +168,36 @@ Use any combination of the three following approaches to make Java classes inter
|
|
|
|
|
|
This is how you respond to an +++<abbr title="Graphical User Interface">GUI</abbr>+++ interaction such as clicks in XML GUIs:
|
|
This is how you respond to an +++<abbr title="Graphical User Interface">GUI</abbr>+++ interaction such as clicks in XML GUIs:
|
|
|
|
|
|
-. Add `visibleToMouse=“true` to the parent element!
|
|
|
|
-. Embed the `<interact />` element into the parent element.
|
|
|
|
-. Specify the Java methods that you want to call when the users performs certain actions, such as clicking. +Example: `<interact onClick=“startGame(hud) />`
|
|
|
|
|
|
+. Add `visibleToMouse="true"` to the parent element!
|
|
|
|
+. Embed the `<interact />` element into the parent element.
|
|
|
|
+. Specify the Java methods that you want to call when the users performs certain actions, such as clicking. +
|
|
|
|
+Example: `<interact onClick="startGame(hud)" />`
|
|
|
|
|
|
Or this is how you respond to an +++<abbr title="Graphical User Interface">GUI</abbr>+++ interaction such as clicks in Java GUIs:
|
|
Or this is how you respond to an +++<abbr title="Graphical User Interface">GUI</abbr>+++ interaction such as clicks in Java GUIs:
|
|
|
|
|
|
. Add `visibleToMouse(true);` to the parent element!
|
|
. Add `visibleToMouse(true);` to the parent element!
|
|
-. Embed one of the `interact…()` elements into the parent element
|
|
|
|
-. Specify the Java method that you want to call after the interaction. +Example: `interactOnClick(“startGame(hud));`
|
|
|
|
|
|
+. Embed one of the `interact…()` elements into the parent element.
|
|
|
|
+. Specify the Java method that you want to call after the interaction. +
|
|
|
|
+Example: `interactOnClick("startGame(hud)");`
|
|
|
|
|
|
In the following example, we call the `startGame()` method when the player clicks the Start button, and `quitGame()` when the player clicks the Quit button.
|
|
In the following example, we call the `startGame()` method when the player clicks the Start button, and `quitGame()` when the player clicks the Quit button.
|
|
|
|
|
|
[source,xml]
|
|
[source,xml]
|
|
----
|
|
----
|
|
|
|
|
|
- <panel id="panel_bottom_left" height="50%" width="50%" valign="center" childLayout="center">
|
|
|
|
- <control name="button" label="Start" id="StartButton" align="center" valign="center"
|
|
|
|
- visibleToMouse="true" >
|
|
|
|
- <interact onClick="startGame(hud)"/>
|
|
|
|
- </control>
|
|
|
|
- </panel>
|
|
|
|
|
|
+<panel id="panel_bottom_left" height="50%" width="50%" valign="center" childLayout="center">
|
|
|
|
+ <control name="button" label="Start" id="StartButton" align="center" valign="center"
|
|
|
|
+ visibleToMouse="true" >
|
|
|
|
+ <interact onClick="startGame(hud)"/>
|
|
|
|
+ </control>
|
|
|
|
+</panel>
|
|
|
|
|
|
- <panel id="panel_bottom_right" height="50%" width="50%" valign="center" childLayout="center">
|
|
|
|
- <control name="button" label="Quit" id="QuitButton" align="center" valign="center"
|
|
|
|
- visibleToMouse="true" >
|
|
|
|
- <interact onClick="quitGame()"/>
|
|
|
|
- </control>
|
|
|
|
- </panel>
|
|
|
|
|
|
+<panel id="panel_bottom_right" height="50%" width="50%" valign="center" childLayout="center">
|
|
|
|
+ <control name="button" label="Quit" id="QuitButton" align="center" valign="center"
|
|
|
|
+ visibleToMouse="true" >
|
|
|
|
+ <interact onClick="quitGame()"/>
|
|
|
|
+ </control>
|
|
|
|
+</panel>
|
|
|
|
|
|
----
|
|
----
|
|
|
|
|
|
@@ -196,24 +227,24 @@ control(new ButtonBuilder("QuitButton", "Quit") {{
|
|
|
|
|
|
----
|
|
----
|
|
|
|
|
|
-Back in the MyStartScreen class, you specify what the `startGame()` and `quitGame()` methods do. As you see, you can pass String arguments (here `hud`) in the method call. You also see that you have access to the app object.
|
|
|
|
|
|
+Back in the MyStartScreen class, you specify what the `startGame()` and `quitGame()` methods do. As you see, you can pass String arguments (here `hud`) in the method call. You also see that you have access to the Application object.
|
|
|
|
|
|
[source,java]
|
|
[source,java]
|
|
----
|
|
----
|
|
|
|
|
|
-public class MyStartScreen implements ScreenController {
|
|
|
|
|
|
+public class MyStartScreen extends BaseAppState implements ScreenController {
|
|
...
|
|
...
|
|
|
|
|
|
- /** custom methods */
|
|
|
|
|
|
+ /** custom methods */
|
|
public void startGame(String nextScreen) {
|
|
public void startGame(String nextScreen) {
|
|
nifty.gotoScreen(nextScreen); // switch to another screen
|
|
nifty.gotoScreen(nextScreen); // switch to another screen
|
|
// start the game and do some more stuff...
|
|
// start the game and do some more stuff...
|
|
}
|
|
}
|
|
|
|
|
|
public void quitGame() {
|
|
public void quitGame() {
|
|
- app.stop();
|
|
|
|
|
|
+ getApplication().stop();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
...
|
|
...
|
|
}
|
|
}
|
|
|
|
|
|
@@ -221,12 +252,12 @@ public class MyStartScreen implements ScreenController {
|
|
|
|
|
|
The startGame() example simply switches the +++<abbr title="Graphical User Interface">GUI</abbr>+++ to the `hud` screen when the user clicks Start. Of course, in a real game, you would perform more steps here: Load the game level, switch to in-game input and navigation handling, set a custom `running` boolean to true, attach custom in-game AppStates – and lots more.
|
|
The startGame() example simply switches the +++<abbr title="Graphical User Interface">GUI</abbr>+++ to the `hud` screen when the user clicks Start. Of course, in a real game, you would perform more steps here: Load the game level, switch to in-game input and navigation handling, set a custom `running` boolean to true, attach custom in-game AppStates – and lots more.
|
|
|
|
|
|
-The quitGame() example shows that you have access to the application `app` object because you made the ScreenController extend AbstractAppState. (If you're creating code from this example, note that you'll need to make sure `app` is initialized before you can successfully call its methods.)
|
|
|
|
|
|
+The quitGame() example shows that you have access to the Application object because you made the ScreenController extend BaseAppState.
|
|
|
|
|
|
|
|
|
|
=== GUI Gets Return Value from Java Method
|
|
=== GUI Gets Return Value from Java Method
|
|
|
|
|
|
-When the Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ is initialized, you can get data from Java. In this example, the Java class `getPlayerName()` in `MyStartScreen` defines the Text that is displayed in the textfield before the words `'s Cool Game`.
|
|
|
|
|
|
+When the Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ is initialized, you can get data from Java. In this example, the Java class `getPlayerName()` in `MyStartScreen` defines the Text that is displayed in the textfield before the words `'s Cool Game`.
|
|
|
|
|
|
First define a Java method in the screen controller, in this example, `getPlayerName()`.
|
|
First define a Java method in the screen controller, in this example, `getPlayerName()`.
|
|
|
|
|
|
@@ -269,7 +300,7 @@ You can use this for Strings and numeric values (e.g. when you read settings fro
|
|
|
|
|
|
=== Java Modifies Nifty Elements and Events
|
|
=== Java Modifies Nifty Elements and Events
|
|
|
|
|
|
-You can also alter the appearance and functions of your nifty elements from Java. Make certain that the element that you want to alter has its `id=“name` attribute set, so you can identy and address it.
|
|
|
|
|
|
+You can also alter the appearance and functions of your nifty elements from Java. Make certain that the element that you want to alter has its `id="name"` attribute set, so you can identy and address it.
|
|
|
|
|
|
Here's an example of how to change an image called `playerhealth`:
|
|
Here's an example of how to change an image called `playerhealth`:
|
|
|
|
|
|
@@ -285,7 +316,7 @@ niftyElement.getRenderer(ImageRenderer.class).setImage(img);
|
|
|
|
|
|
----
|
|
----
|
|
|
|
|
|
-The same is valid for other elements, for example a text label “score:
|
|
|
|
|
|
+The same is valid for other elements, for example a text label "`score`":
|
|
|
|
|
|
[source,java]
|
|
[source,java]
|
|
----
|
|
----
|
|
@@ -307,7 +338,7 @@ niftyElement.getElementInteraction().getPrimary().setOnMouseOver(new NiftyMethod
|
|
|
|
|
|
----
|
|
----
|
|
|
|
|
|
-For this to work, there already needs to be a (possibly inactive) `<interact />` tag inside your xml element:
|
|
|
|
|
|
+For this to work, there already needs to be a (possibly inactive) `<interact />` tag inside your xml element:
|
|
|
|
|
|
[source,xml]
|
|
[source,xml]
|
|
----
|
|
----
|
|
@@ -320,4 +351,4 @@ For this to work, there already needs to be a (possibly inactive) `<interact
|
|
You're done with the basic Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ for jME3 tutorial. You can proceed to advanced topics and learn how add controls and effects:
|
|
You're done with the basic Nifty +++<abbr title="Graphical User Interface">GUI</abbr>+++ for jME3 tutorial. You can proceed to advanced topics and learn how add controls and effects:
|
|
|
|
|
|
* <<jme3/advanced/nifty_gui_scenarios#, Nifty GUI Scenarios>>
|
|
* <<jme3/advanced/nifty_gui_scenarios#, Nifty GUI Scenarios>>
|
|
-* link:http://sourceforge.net/projects/nifty-gui/files/nifty-gui/nifty-gui-the-manual-v1.0.pdf/download[Nifty GUI - the Manual]
|
|
|
|
|
|
+* link:https://versaweb.dl.sourceforge.net/project/nifty-gui/nifty-gui/1.3.2/nifty-gui-the-manual-1.3.2.pdf[Nifty GUI - the Manual]
|