Lemur ListBox How to use the programmed control slider?


I made a simple console
I set listBox.setVisibleItems(13);

When the content exceeds 13 I want the slider bar to be at the max value not the min value

Which function should I use to set the ListBox?

http://jmonkeyengine-contributions.github.io/Lemur/javadoc/LemurProto/com/simsilica/lemur/ListBox.html#getSlider--
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/Slider.html#getModel--
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/RangedValueModel.html#setValue-double-
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/RangedValueModel.html#getMaximum--

1 Like

Slider…
I missed this doc, thanks for the tip :sweat_smile:

I’m having some problems.

        ListBox listBox = new ListBox<>();
        ConsolesUI.addChild(listBox);
        listBox.setVisibleItems(13);

        textField.getActionMap().put(new KeyAction(KeyInput.KEY_RETURN), new KeyActionListener() {
            @Override
            public void keyAction(TextEntryComponent arg0, KeyAction arg1) {
                //double min = listBox.getSlider().getModel().getMinimum();
                
                ParseTools(textField.getText());
                listBox.getModel().add(">"+textField.getText());
                textField.setText("");
                listBox.getSlider().getModel().setPercent(0);
           }
});

With the above code, I found that when ListBox > 13 the slider is not at the minimum value, it is always a little more than the minimum value.

System.err.println(listBox.getSlider().getModel().getPercent()); The return result is
{F@VVOD(CPSRLX5K1}1`Y

This confuses me a bit, how should I fix this?

Could be a couple different things. Displaying only “percent” hides most of the useful information, though. I also don’t know where you are printing that value in the context of other things.

I’m monumentally busy this week and so already in a bad mood… so take that into account when I say that it’s super frustrating trying to help folks when they only show me 1-2 lines of “code they think is relevant”.

Anyway, without knowing anything useful other than the three actual lines of code doing anything, my guess would be that where you update the percent (immediately after adding to the model) that the slider hasn’t been updated yet… so you set the percent to 0 but the listbox sees the model has changed and updates the slider’s model on the next update.

If you want the list box to always be at the bottom then you should get a VersionedReference to the model and when you see that change, set the slider position to 0 again.

Edit: like in some update method:

if( modelRef.update() ) {
    slider.setValue(0);
}

Edit 2: alternately, you might be able to app.enqueue() setting the slider right after your add… but I think enqueued stuff runs before the spatials get updated so it might not be far enough in the future.

Thank you for replying in your busy schedule.

/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package GUI;

import SelectUnit.Hominini.T100;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.BaseAppState;
import com.jme3.asset.AssetManager;
import com.jme3.font.BitmapFont;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.simsilica.lemur.ActionButton;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.CallMethodAction;
import com.simsilica.lemur.Command;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.ListBox;
import com.simsilica.lemur.Slider;
import com.simsilica.lemur.TextField;
import com.simsilica.lemur.component.BorderLayout;
import com.simsilica.lemur.component.BorderLayout.Position;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.component.TextEntryComponent;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.event.ConsumingMouseListener;
import com.simsilica.lemur.event.KeyAction;
import com.simsilica.lemur.event.KeyActionListener;
import com.simsilica.lemur.event.MouseEventControl;
import com.simsilica.lemur.style.BaseStyles;
import com.simsilica.lemur.style.ElementId;
import java.util.ArrayList;
import java.util.List;
import jme3utilities.minie.FilterAll;
import static physicsState.MinieBulletAppState.bulletAppState;

/**
 *
 * @author icyboxs
 */
public class ConsolesUI<T> extends BaseAppState implements ActionListener{

    private InputManager inputManager;
    private AssetManager assetManager;
    private SimpleApplication simpleApp;
    private Camera cam;
    private BitmapFont font;
    private ListBox listBox;
    private static final StringBuilder ConsoleMsg = new StringBuilder();
    private Container ConsolesUI;
    private boolean ConsoleSwitch=false;
    private VersionedReference<List<T>> modelRef;
    @Override
    protected void initialize(Application aplctn) {
        simpleApp = (SimpleApplication) aplctn;
        assetManager = aplctn.getAssetManager();
        inputManager = aplctn.getInputManager();
        cam = aplctn.getCamera();
        GuiGlobals.initialize(simpleApp);
        BaseStyles.loadGlassStyle();
        GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");
        font = assetManager.loadFont("Textures/font/FontCJK/fontCJK.fnt");
        GuiGlobals.getInstance().getStyles().setDefault(font);
        BaseStyles.loadStyleResources("/Textures/UI/ListBoxStyle.groovy");
        GuiGlobals.getInstance().getStyles().setDefaultStyle("ListBoxGlass");
        inputManager.addMapping("`",  new KeyTrigger(KeyInput.KEY_GRAVE));
        inputManager.addListener(this, "`");
        InitialisingUI();
        this.modelRef=listBox.getModel().createReference();
    }

    @Override
    protected void cleanup(Application app) {

    }

    @Override
    protected void onEnable() {
        simpleApp.getGuiNode().attachChild(ConsolesUI);
    }

    @Override
    protected void onDisable() {
    simpleApp.getGuiNode().detachChild(ConsolesUI);
    }

        @Override
    public void update(float tpf) {
   
    if(modelRef.update()){
    listBox.getSlider().getModel().setValue(0);
    }
    this.modelRef=listBox.getModel().createReference();
    }
    
    
    
    
    
    public void ParseTools(String msg) {
        if (msg.startsWith("/")) {
            int spaceIndex = msg.indexOf(" "); // 在斜杠之后查找空格
            if (spaceIndex != -1) {
                String Command = msg.substring(1, spaceIndex);
                System.out.println(Command);

                ArrayList count = countSpaces(msg);
                System.out.println(count);
                RunCommand(Command, count);
            } else {
                String Command = msg.substring(1, msg.length());
                System.out.println(Command);
                RunCommand(Command);
            }

//        String result = msg.substring((int)count.get(0)+1, (int)count.get(1));
//        System.out.println(result);
        }

    }

    private ArrayList countSpaces(String str) {
        int spaceCount = 0;
        ArrayList<Integer> sites = new ArrayList<Integer>();
        ArrayList<Object> ValueSorted = new ArrayList<Object>();
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == ' ') {
                spaceCount++;
                sites.add(i);
            }
        }

        for (int i = 0; i <= sites.size() - 1; i++) {
            if (sites.size() - 1 == i) {
                String result = str.substring((int) sites.get(i) + 1, str.length());
//        System.out.println(result);
                ValueSorted.add(result);
            } else {
                String result = str.substring((int) sites.get(i) + 1, (int) sites.get(i + 1));
//        System.out.println(result);
                ValueSorted.add(result);
            }

        }
        return ValueSorted;
    }

    private void RunCommand(String Command, ArrayList count) {
        switch (Command) {
            case "add":
                if(count.size()==3){

                for(int i=0;i<=Integer.parseInt((String) count.get(2))-1;i++){
                T100.addT101(new Vector3f(Float.parseFloat((String) count.get(0)), 0, Float.parseFloat((String) count.get(1))), simpleApp);
                }
                }
                //T100.addT101(new Vector3f(Float.parseFloat((String) count.get(0)), 0, Float.parseFloat((String) count.get(1))), simpleApp);
                break; //可选
            case "exit":
                simpleApp.stop();
                break; //可选
            case "cam":
                System.err.println();
                cam.setLocation(new Vector3f(0,cam.getLocation().y,-200f));
                break; //可选
            case "physDebug":

                    
                    bulletAppState.setDebugBoundingBoxFilter(new FilterAll(!bulletAppState.isDebugEnabled()));
                    bulletAppState.setDebugEnabled(!bulletAppState.isDebugEnabled());

                break; //可选
            default: //可选
                //语句
                listBox.getModel().add(">" + "未知命令");
        }

    }

    private void RunCommand(String Command) {
        RunCommand(Command, null);
    }

    @Override
    public void onAction(String name, boolean isPressed, float tpf) {
                if (name.equals("`") && !isPressed) {
                simpleApp.getStateManager().getState(ConsolesUI.class).setEnabled(ConsoleSwitch);
                ConsoleSwitch=!ConsoleSwitch;
            }
    }
    private void InitialisingUI(){
        
        ConsolesUI = new Container(new BorderLayout());
        ConsolesUI.setPreferredSize(new Vector3f(cam.getWidth() / 2, cam.getHeight() / 2, 0));
        ConsolesUI.setLocalTranslation(0, 1080, 0);
        System.out.println(cam.getHeight());
        System.out.println(cam.getWidth());
        Container TextFieldPlusButton = new Container();

        ConsolesUI.addChild(TextFieldPlusButton, Position.South);

        listBox = new ListBox<>();
        ConsolesUI.addChild(listBox);
        listBox.setVisibleItems(2);

        TextField textField = new TextField("");
        textField.setFontSize(25f);
        textField.setFont(font);
        textField.setSingleLine(false);
        textField.getActionMap().put(new KeyAction(KeyInput.KEY_RETURN), new KeyActionListener() {
            @Override
            public void keyAction(TextEntryComponent arg0, KeyAction arg1) {
                //double min = listBox.getSlider().getModel().getMinimum();
                
                listBox.getModel().add(">" + textField.getText());
                
                //listBox.getModel().createReference().update();
//                listBox.getModel().createReference();
                

                ParseTools(textField.getText());
                textField.setText("");
                
            }
        });
        TextFieldPlusButton.addChild(textField, 0, 0);

        //标题
        Label label = new Label("Consoles");
        label.setFont(font);
        label.setFontSize(25f);
        label.setColor(ColorRGBA.Blue);
        ConsolesUI.addChild(label, Position.North);
        
    }
    
}

    

This is the complete content.

I tried to set listBox.getSlider().getModel().setValue(0);

But it was still done before the slider was updated.
This results in the slider always being a little less than the final.
The slider is always not at the bottom (min).

 textField.getActionMap().put(new KeyAction(KeyInput.KEY_RETURN), new KeyActionListener() {
            @Override
            public void keyAction(TextEntryComponent arg0, KeyAction arg1) {
                //double min = listBox.getSlider().getModel().getMinimum();
                
                listBox.getModel().add(">" + textField.getText());
//                listBox.getModel().createReference();
//                listBox.getSlider().getModel().setValue(0);

                ParseTools(textField.getText());
                textField.setText("");
                
            }
        });

I tried the other way but it didn’t work.
I cannot set the slider of the listbox to .setValue(0) after updating the listbox’s parameters in the operation of KEY_RETURN.

When I set .setValue(0) the Listbox doesn’t seem to have finished updating this causes the slider to always be at 1 less than the minimum value.

There doesn’t seem to be a way for me to immediately update the ListBox list in a single keystroke operation and then do a .setValue(0) in the.

        @Override
    public void update(float tpf) {
   
    if(modelRef.update()){
    listBox.getSlider().getModel().setValue(0);
    }
    this.modelRef=listBox.getModel().createReference();
    }

What I’m trying to do in update,Still having the same problem

My current idea is to modify parts of the ListBox,Because there is no function that I can call to make the ListBox update immediately.

Is there another way I can achieve my goal without modifying the ListBox?

I don’t know.

This code makes no sense. Why do you get the reference after you call update()? Just wasted code.

What update() method is that?

The chat seems to be in a dead end, I guess I seem to have misinterpreted your expression

Through this content, I try to implement the above operation in the update.
It seems to be working.
Because he also implemented making the slider appear at the bottom (but not quite at the bottom).

        @Override
    public void update(float tpf) {
   
    if(modelRef.update()){
    listBox.getSlider().getModel().setValue(0);
    }
    this.modelRef=listBox.getModel().createReference();
    }
 textField.getActionMap().put(new KeyAction(KeyInput.KEY_RETURN), new KeyActionListener() {
            @Override
            public void keyAction(TextEntryComponent arg0, KeyAction arg1) {
                //double min = listBox.getSlider().getModel().getMinimum();
                
                listBox.getModel().add(">" + textField.getText());
//                listBox.getModel().createReference();
                listBox.getSlider().getModel().setValue(0);

                ParseTools(textField.getText());
                textField.setText("");
                
            }
        });

Both ways achieve the same effect but not the one I want (the sliders appear a little bit in front of the bottom).


I don’t know why when listBox.getSlider().getModel().setValue(0); the value becomes 1.0 again after this is executed.

When I look at the code it seems to execute listBox.getSlider().getModel().setValue(0); nothing else is added but here the value becomes 1.0 which is strange to me

(I seem to have compounded the problem, I think I should go to bed and reorganise the content)

Change that to:

        @Override
    public void update(float tpf) {
   
    if(modelRef.update()){
        getApplication().enqueue( () -> {
            listBox.getSlider().getModel().setValue(0);
        }
    }
    this.modelRef=listBox.getModel().createReference();
    }

Though honestly, you might as well call:

    this.modelRef=listBox.getModel().createReference();

5,000,000 times if you want to be truly wasteful.

You do not need to call that here.

2 Likes

Perfect solution to the problem thanks for the help

1 Like