How to use onSliderChanged in nifty XML?

I am checking out Nifty to see if I can get it running. But I get stuck at getting my code to react on the changing of a slider.

I use XML to create my gui and style it. I have the following code for a slider:

         <control id="seaLvl" name="horizontalSlider" width="65%" height="16px">
              <interact onSliderChange="changeSeaLevel()"/>
          </control>

But during validating the XML I get the following error:

Attribute ‘onSliderChange’ is not allowed to appear in element ‘interact’.

Fine with me, but where do I use this to capture sliding events and direct them to my code?

You can just subscribe to it in your screen controller class:

  @NiftyEventSubscriber(id="seaLvl")
  public void onMySliderChange(String id, SliderChangedEvent event) {
    derp();
  }
1 Like

Same goes to i.e. Comboboxes and some other things. They just generate these events automatically. Those interacts are for when you kinda create an event or interaction for a control. With Sliders these are automatic or inert.

Just to warn you. Nifty isn’t exactly deprecated, but it isn’t exactly supported either. Very few new projects start with Nifty (and some like mine have painfully transfered off it when we fully understood how painful it was).

Lemur is pretty much defacto standard at this point but there are several better supported ui libraries out there¹.

¹ I struggled to make that sentence exactly clear. Better supported than Nifty

3 Likes

Thanks,

I only turned to Nifty to mock up a quick interface that allows me to tweak parameters during development. I expect to use Lemur later on to create my own ingame controls.

Currently I need to see the effect of parameters in my shaders:

The terrain and water shaders are dynamic and will adjust according to the sealevel, the climate and more.

4 Likes

Out of fun, and offtopic, but here you have the some code to create your panel with lemur:
Capture

public class Parameters extends Container {
    Label title;
    Label waterLevel;
    Label climate;
    Slider waterLevelSlider;
    Slider climateSlider;

    public Parameters() {
        super(new BorderLayout());
        Container container = new Container(new SpringGridLayout(Axis.X, Axis.Y, FillMode.Last, FillMode.None));
        title = new Label("World Parameters");
        title.setFontSize(20f);
        addChild(title, BorderLayout.Position.North);
        addChild(container, BorderLayout.Position.Center);
        waterLevel = new Label("Sea Level:");
        climate = new Label("Climate:");
        waterLevelSlider = new Slider();
        climateSlider = new Slider();
        container.addChild(waterLevel, 0, 0);
        container.addChild(waterLevelSlider, 1, 0);
        container.addChild(climate, 0, 1);
        container.addChild(climateSlider, 1, 1);
    }
}
1 Like

Intreresting, but I would primarely be interested in how to capture and handle the events of the sliders.

        //Get a reference 
        VersionedReference<Double> reference = slider.getModel().createReference();

        //Inside a control.update or a state.update
        if (reference.update()) {
            double value = reference.get();
            //update your stuff
        }

And i am sure there is also a way for a more classical event based method.

Events are super-wasteful. Since JME is polling all the time anyway, it doesn’t use events for simple state checks. That avoids: event creation garbage, processing redundant events, listener creation garbage, remembering to remove your listeners later to not have memory leaks, etc…

VersionedReference is garbage-free, zero-overhead, zero extra management, etc… and it gets checked never more often than needed.

But if you want to do it like Nifty does with all of the wired up classes, you can do it that way: just implement RangedValueModel and set that as the model for the slider. Then you will be called for every value change just like in nifty. (Or extend DefaultRangedValueModel and override the appropriate method.)

Edit: I should also add the zuegg’s example is exactly right. Very clean in fact. Get a reference when you initialize the UI panel then monitor it in update.

1 Like