What's up with nifty?

I played around with nifty today and it seems to be very difficult to get a simple gui running.



I have a listbox with items and i cant get the click events. I figured out that there is a method invoke and get a method called in my controller, but an event or other params aren't send. Furthermore there are no abstract classes or interfaces to implement to get it easily extended/running, no tutorials at the inet and i had to read all the sources to get how it should work .

Nifty looks really nice but it seems to be hardly extensible and i'm wondering if there's a thing i don't understand.

BUI on jme2 was easily to understand and extend compared to nifty.

Can anybody give me a tutorial link or a hint how to get a "real life"-gui working?

I think you’ve found the webstart tutorial because you’ve already commented on the nifty gui blog. The tutorial webstarts shows a whole lot about basic ideas behind nifty and how it works tho.



> Furthermore there are no abstract classes or interfaces to implement to get it easily extended/running



What for? :?



> no tutorials at the inet



Not true!



> BUI on jme2 was easily to understand and extend compared to nifty.



Keep using it? o_O



> Can anybody give me a tutorial link or a hint how to get a “real life”-gui working?



Maybe you can take a look at the nifty-examples project too https://nifty-gui.svn.sourceforge.net/svnroot/nifty-gui/nifty-examples/trunk ? It shows in examples how to get a listbox selection for instance.



More resources are:



Wiki: https://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Main_Page

Sourceforge Project: https://sourceforge.net/projects/nifty-gui/

Nifty Help forum at sf.net: https://sourceforge.net/projects/nifty-gui/forums/forum/807893



And what are your issues with extending nifty? Nifty is not at all hardly extensible but I guess that really depends on what you mean by “extensible” anyway or what you are trying to do.



What do you mean by: “I can’t get the click events”?



I think the first or second page of the tutorial webstart states clearly that: “Nifty is not an application framwork and it is not a Widget Toolkit (like AWT, Swing or even SWT). If you need a solution with lots of controls, windows, dialog boxes and so on, you might want to look somewhere else.”. Nifty is different and yes maybe a bit hard to learn in the beginning - although I think the basics are covered well in the tutorial webstart.

void256 said:

> Furthermore there are no abstract classes or interfaces to implement to get it easily extended/running
What for? :?


To have professional code.

For example, the rendering system, even in JME3, is purely designed.
Why there is no MeshRenderer interface and several implementations that actually prepare and send buffers to the shaders/OpenGL? Same thing with Material class. There is no clear interface to write a separate implementation.

I think Material and MaterialParameters should be two different interfaces/classes so you can easily change/swap parameters for the Material. In this case MaterialParameters may be a simple POJO  object which can be marshaled/unmarshaled using JAXB.

There is only one pretty huge Renderer interface and one implementation for LWGJL/JOGL/Android platforms.
It is really difficult to extend the existent functionality without going directly to the source code of the engine and changing system classes.

But don't take me wrong. I love JMonkeyEngine and try to use it everywhere I can. (Usually I have to fight with my co-workers that use Unity3D).


Ooh, sry void i didnt want to offend you.



I read the examples (i have the whole project checked out) and couldn't find a simple solution using the existing code.

And by the way, reading source code is not the way to use a framework.



I also checked the forum out where i couldnt find a hint.



Abstracts would be a good way to find out how things should be used.(e.g. which mehtods must be overriden and using existing code).



In my special problem i wanted to know which listboxitem is clicked and i think i found a way after reading source for 4 hours.



So thx for your work and perhaps theres a way to make it more feeling like swing with listeners and events and such nice things.

I’m not offended. It just seems that when you say “GUI” you mean the JFC/SWING way of creating GUIs that Nifty - by design - does not offer. There is no Widget Hierachy that starts with a abstract base class in Nifty like you might be used to from other GUI frameworks.



This, however, is not a mistake - it is done by design. If you’re interessted in some of the thoughts that went into it, I’ve blogged about it some time ago http://nifty-gui.lessvoid.com/archives/6



Controls (Buttons, DropDown, Textfield, ListBox, and so on) are just one way you can use Nifty. Its not the only one: If you want a scoreboard or a weapon select “GUI” for your ingame HUD then Nifty can provide that too. You don’t have to use the standard controls project for this! You can simply use Niftys core elements or combine them to form your own controls http://nifty-gui.lessvoid.com/archives/11. You’re usually not make MyButton extends Button in Nifty! This is done by design too and it is not a missing feature.



So, are there some things missing in Nifty? Yes!



It lacks documentation, yeah. But that situation is (slowly) improving. Why not get involved and share what you’ve learned with your listbox problem? It might help others to solve the same problem.



It lacks some high level “event” handling for the standard controls. Yes, maybe. I think you want something like the DropDownControlNotify interface that already exists for the Nifty DropDownControl, right? You could get involved for this missing feature too. Why not post a feature request in Nifty’s Feature Request tracker when you miss a certain functionality? Another great way to help woule be to get even more involved and send a patch like others already did?

Yeah, I can agree, it is very hard to understand what I have to do to get nifty to do it, when you are new, thats why I'm working on this:



http://www.jmonkeyengine.com/forum/index.php?topic=14315.0

Thats a great idea. As soon as i get nifty running again (it's currently broken and i have to figure it out) i will test and share the things i develop for that.

Thats great, a swing to jme bridge is a good idea i think. Nevertheless i will try nifty a little time cause it seems to be a good thing.



I'm thinking about contribute the jme project and this topic would be a good fit cause i'm very experienced in Swing/AWT/SWT.

Rally ? I'm currently stuff at the point where I want to simulate Key and Mouse events, but I don't know what I have to call and read java docs at random in the hope to find something.

So…, back to topic! Nice to see nifty running again.



I solved my problem with extending nifty's ListBoxControl class (empty lines removed for space):



public class NotifyingListBoxControl extends ListBoxControl {

private List<SelectionListener> listeners = new ArrayList<SelectionListener>();

@Override

public void changeSelection(final Element element) {

super.changeSelection(element);

fireOnSelectionChanged(getSelectedItemIndex());

}

protected void fireOnSelectionChanged(int i) {

for (SelectionListener listener : listeners)

listener.onSelectionChanged(i);

}

public void addSelectionListener(SelectionListener listener) {

listeners.add(listener);

}

public void removeSelectionListener(SelectionListener listener) {

listeners.remove(listener);

}

}



And "writing" my own listbox control xml by copying the whole nifty-listbox.xml and changing the line:



<controlDefinition name="stationchooser" style="nifty-listbox"

childRootId="nifty-listbox-child-root"

controller="model.scene.ui.hud.NotifyingListBoxControl">



Now i can add listeners to the control and get notified with the new selected index.

The SelectionListener Code has been added to the ListBoxControl control in the nifty-default-controls project.



Thanks and I accept svn .patch files too! :smiley:

Cool! :smiley:



What do you mean with accepting svn .patch files? I'm not familiar with that.

Well, if you "svn check out" a subversion project and you make changes to it but you have no way to commit these changes back to the repository you can create a special file, the so called "patch" file that contains all of your changes. It's a text file in a special format that contains the diffs of all the files you've changed or added or deleted. You can then send this file to someone else who can apply this patch to his version of the project or he can commit it back to the subversion repository.



You can probably create the files with the svn commandline tool but I'm using eclipse and there is a "team / create patch …" menu item in the popup menu for a project you've checked out with subversion in eclipse.

Ok, thx for advice.

Just another Listener for textfields:

Well, I'd love to add this too but this is a somewhat odd patch file. When I try to apply it to a project with "Team / Apply Patch…" using eclipse it complains at says that it's not a valid patch file  :?



In the first line of the file it says:

### Eclipse Workspace Patch 1.0





Although the remaining of the file looks like a svn patch file I'm a bit confused now :slight_smile: I'm curious what a Eclipse Workspace Patch this is and how you've created it because I've never seen this before? I don't seem to find a menu entry to apply this patch. Can you help me this time? :slight_smile:



I've been able to apply real SVN Patch files (without that odd lines in the beginning) without problems for years. So I'm a bit confused now :smiley:



Can you try to create the patch file again? Maybe with the project selected or so?



And it would be a lot easier for me to see the actual changes if you don't change the source formating when sending a patch. I know that source formatting is an interessting topic that everybody has a different preference for. But in a patch it would be greatly appreciated when there won't be lot of changes like tabs replaced with whitespaces or other changes of the source code format. Simply to see the actual changes better!



Thank you for your effort!

Hi,



i created the patch by right clicking on the project - team and Create Patch in eclipse with subclipse eclipse plugin.

There's another option "Apply patch" but i've never tried that before.



I don't know what is going wrong here.



And sry about formatting, its a standard behavior for my save options to format the code with eclipse standard format options.



I created the patch again, but the ### Eclipse Workspace Patch 1.0 is in there again.



I add the source here in case that it doesn't work with the patch.


private List<ActionListener> listeners = new ArrayList<ActionListener>(0);

   public static interface ActionListener {
      public void onActionEvent(ActionEvent e);
   }

   public static class ActionEvent {
      private final NiftyInputEvent inputEvent;
      private final TextField textField;

      public ActionEvent(final NiftyInputEvent inputEvent, TextField textField) {
         this.inputEvent = inputEvent;
         this.textField = textField;
      }

      public NiftyInputEvent getInputEvent() {
         return inputEvent;
      }

      public TextField getTextField() {
         return textField;
      }

   }

        public void addActionListener(ActionListener listener) {
      listeners.add(listener);
   }

   public void removeActionListener(ActionListener listener) {
      listeners.remove(listener);
   }

   protected void fireOnActionEvent(ActionEvent event) {
      for (ActionListener listener : listeners)
         listener.onActionEvent(event);
   }

        public boolean inputEvent(final NiftyInputEvent inputEvent) {
      if (inputEvent != null) {
         ActionEvent event = new ActionEvent(inputEvent, textField);
         if (inputEvent == NiftyInputEvent.MoveCursorLeft) {
            textField.cursorLeft();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.MoveCursorRight) {
            textField.cursorRight();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.Delete) {
            textField.delete();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.Backspace) {
            textField.backspace();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.MoveCursorToLastPosition) {
            textField.toLastPosition();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.MoveCursorToFirstPosition) {
            textField.toFirstPosition();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.SelectionStart) {
            textField.startSelecting();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.SelectionEnd) {
            textField.endSelecting();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.Cut) {
            textField.cut(passwordChar);
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.Copy) {
            textField.copy(passwordChar);
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.Paste) {
            textField.put();
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.SubmitText) {
            fireOnActionEvent(event);
         } else if (inputEvent == NiftyInputEvent.Character) {
            textField.insert(inputEvent.getCharacter());
            updateCursor();
            fireOnActionEvent(event);
            return true;
         } else if (inputEvent == NiftyInputEvent.NextInputElement) {
            if (focusHandler != null) {
               focusHandler.getNext(fieldElement).setFocus();
               updateCursor();
               fireOnActionEvent(event);
               return true;
            }
         } else if (inputEvent == NiftyInputEvent.PrevInputElement) {
            textField.endSelecting();
            if (focusHandler != null) {
               focusHandler.getPrev(fieldElement).setFocus();
               updateCursor();
               fireOnActionEvent(event);
               return true;
            }
         }
         updateCursor();
         fireOnActionEvent(event);
      }
      return false;
   }


By the way,



i don't see the reason why to invoke methods on a complex gui when it has listeners on its component's:



WARNUNG: method [onClick()] not found at object class [class model.scene.ui.hud.controller.LoginController]



Cause there's no hint where it's clicked and which state the click has.



Please don't missunderstand my thought's, i think nifty rocks and it's worth to learn how to use it.

I don't know where this specific onClick() comes from.



Just some notes about Niftys inner workings - you said you want to learn them, right? :stuck_out_tongue:



At it's core Nifty really is Panel, Image and Text. I mean there are really only these basic elements. Everything else, every Button, Listbox or Scrollbar is build from these elements- There are effects that can be added to the core elements for different states of the elements as well as interactions like onClick, onMouseMove and so on.



This means that Niftys standard controls are all build out of these basic components using the same interaction possibilities that are available to the elements. When you click on a listbox element there really is an onClick() invoke performed on one of the basic elements.



So that is the reason that there are method invokes like onClick() even when there are listeners available (that are in the end triggered by an onClick() on some interact tag on some panel, image or element)



And again, Nifty is not a widget toolkit and I know that this is probably limiting its use and it's not appropriate for very complex GUIs with lots of interconnected controls. On the other hand Nifty allows other kind of GUIs like the tutorial/demo thing which would be more difficult with a traditonal widget toolkit like GUI.

Ok, perhaps a can't accept that nifty isn't a normal gui widget toolkit and perhaps i never will. I'll always try to improve it to feels like :P.



The Method invoke comes from "ElementInteraction" onClick, which is initialized for every "Element". Perhaps it is meant to send parameters with it, but i could'nt get them until now.



Furthermore i cant get the whole range for the usage of nifty and what is needed. So don't feel bad for my questions about it, i want to learn and see how much possibilities it serves.