Interacting with the GUI from Java

  1. Nifty GUI Java Interaction

The main purpose of the GUI is to send events back to your Java class that indicate what the users clicked, which settings they chose, which values they entered into a field, etc. In the Java class, you want to respond with an appropriate action, or store the entered settings in a file, etc.

Connect GUI to Java Controller

How does the XML file send a message back to your Java application? You register a ScreenController (a Java class) to every NiftyGUI screen. Create a ScreenController by creating a Java class that implements the de.lessvoid.nifty.screen.ScreenController interface and its abtract methods.

package my.game;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
public class MySettingsScreen implements ScreenController {
    public MySettingsScreen(MyGameData data ){ /** constructor */ }
    public void bind(Nifty nifty, Screen screen) { }
    public void onStartScreen() { }
    public void onEndScreen() {  }
}

The name and package of your custom ScreenController class (here my.game.MySettingsScreen) goes into the controller parameter of the respective screen it belongs to:

<nifty>
  <screen id="settings" controller="my.game.MySettingsScreen">
      <!-- layer and panel code ... -->
  </screen>
</nifty>

Now the Java class my.game.MySettingsScreen and this GUI screen (settings) are connected.

Make GUI and Java Interact

In most cases, you will want to pass game data in and out of the ScreenController. Note that you can pass any arguments into your ScreenController constructor. In the example above, the object with the necessary data is is MyGameData data. You can use any of the three following approaches to make Java classes interact with the GUI, and you can also combine them, depending on what you want to do.

GUI Calls a Void Java Method

To respond to an interaction, add the <interact /> element to a panel and specify the Java method you want to call. In this example, we want to call sayHello() when a panel on the screen is clicked.

...
<panel id="panel" height="25%" width="35%" align="center" valign="center"
       backgroundColor="#f60f" childLayout="center" visibleToMouse="true">
    <text id="text" font="aurulent-sans-17.fnt" color="#000f"
          text="Hello World!" align="center" valign="center" />
    <interact onClick="sayHello(hi)"/>
</panel>
...

Back in this screen's Java class, we specify what the sayHello() method does. As you see, you can include String arguments in the call.

public class MySettingsScreen implements ScreenController {
  ...
  public void sayHello(String myarg) {
     System.out.println("Nifty says "+myarg);
  }
}

GUI Gets Return Value from Java Method

You can send a message from Java to Nifty. In this example, the Java class callThis() in MySettingsScreen defines the Text that is displayed in the textfield after the words Hello World, …! First define a Java method in the screen controller, in this example, callThis().

public class MySettingsScreen implements ScreenController {
  ...
  public String callThis() {
     return "my friend";
  }
}

Nifty uses ${CALL.callThis()} to get the return value of a method from your ScreenController Java class.

...
<panel id="panel" height="25%" width="35%" align="center" valign="center"
       backgroundColor="#f60f" childLayout="center" visibleToMouse="true">
    <text id="text" font="aurulent-sans-17.fnt" color="#000f"
          text="Hello World, ${CALL.callThis()}!" align="center" valign="center" />
    <interact onClick="sayHello(hi)"/>
</panel>
...

You can also use this for Strings and numeric values, e.g. when you read settings from a file, you read them like this.

Java Modifies Nifty Elements and Events

You can also alter the appearance and functions of your nifty elements from Java. Here's an example of how to change the image myElement:

NiftyImage img = nifty.getRenderEngine().createImage("Interface/Images/image.png", false);
Element niftyElement = nifty.getCurrentScreen().findElementByName("myElement");
niftyElement.getRenderer(ImageRenderer.class).setImage(img);

The same is valid for other elements, for example text fields:

niftyElement.getRenderer(TextRenderer.class).setText("New text");

Similarly, to change the onClick() event of an element, create an ElementInteraction object:

Element niftyElement = nifty.getCurrentScreen().findElementByName("myElement");
niftyElement.getElementInteraction().getPrimary().setOnMouseOver(new NiftyMethodInvoker(nifty, "myCustomMethod()", this));

For this to work, there already needs to be an < interact > tag inside your xml element:

<interact onClick="doNothing()"/>

Concepts & Examples

note: Nifty-gui 1.3 oriented.

How do I create a popup menu that I populate in Java?

Even though you create and populate the popup menu in Java you still need a "placeholder" in your XML file, below is an example extract:

<useControls filename="nifty-default-controls.xml"/>
...
 <popup id="niftyPopupMenu" childLayout="absolute-inside"
	controller="ControllerOfYourChoice" width="10%">
		<interact onClick="closePopup()"
		onSecondaryClick="closePopup()" onTertiaryClick="closePopup()" />
		<control id="#menu" name="niftyMenu" />
 </popup>
...

A brief explanation of some the attributes above:

Java code within your defined ScreenController implementation:

private Element popup;
...
public void createMyPopupMenu(){
        popup = nifty.createPopup("niftyPopupMenu");
	Menu.class);
	myMenu.setWidth(new SizeValue("100px")); //must be set
	myMenu.addMenuItem("Click me!", "menuItemIcon.png", new menuItem("menuItemid", "blah blah")); //menuItem is a custom class
	nifty.subscribe(nifty.getCurrentScreen(), myMenu.getId(), MenuItemActivatedEvent.class, new MenuItemActivatedEventSubscriber());
}
public void showMenu(){ //the method to trigger the menu
   createMyPopupMenu() //you should call this in your constructor rather than here if it is a menu that is going to be used many times
   nifty.showPopup(nifty.getCurrentScreen(), popup.getId(), null); //call the popup to screen of your choice
}
private class menuItem{
   public String id;
   public String name;
   public menuItem(String name){
	this.id= id;
	this.name = name;
   }
}

To handle menu item events (i.e. calling a method when you click on a menu item) you subscribe a EventTopicSubscriber<MenuItemActivatedEvent> class implementation to a nifty screen and element.

private class MenuItemActivatedEventSubscriber implements EventTopicSubscriber<MenuItemActivatedEvent> {
    @Override
    public void onEvent(final String id, final MenuItemActivatedEvent event) {
    	menuItem item = (menuItem) event.getItem();
       if ("menuItemid".equals(item.id)) {
		//do something !!!
       }
    }
};

Useful Links

Nifty 1.3 controls Java Docs: http://nifty-gui.sourceforge.net/projects/1.3-SNAPSHOT/nifty-default-controls/apidocs/

Nifty 1.3 Java Docs: http://nifty-gui.sourceforge.net/projects/1.3-SNAPSHOT/nifty/apidocs/index.html

Examples of standard controls in Nifty 1.3: http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Nifty_Standard_Controls_%28Nifty_1.3%29

Learn more: Nifty Syntax

gui, documentation, input, controller, controllers

view online version