Scroll panel in lemur

I am not sure if this will help you or not.
I am using it in my CellRenderer for GridPanel

/**
 * Used to render 3D Items (items which have spatial) in a Gui panel
 *
 * @author Ali-RS <ali_codmw@yahoo.com>
 */
public class ItemRenderer extends DefaultCellRenderer<Item> {

    protected Map<Item, Spatial> spatials = new HashMap<>();
    private final AppStateManager stateManager;

    public ItemRenderer(AppStateManager stateManager) {
        super(null);
        this.stateManager = stateManager;
    }

    @Override
    public Panel getView(Item item, boolean selected, Panel existing) {

        if (existing == null) {

            //Container container = new Container();
            ViewportPanel container = new ViewportPanel(stateManager, new ElementId(Container.ELEMENT_ID), null);
            existing = container;

            /**
             * A white, directional light source
             */
            DirectionalLight sun = new DirectionalLight();
            sun.setDirection(Vector3f.UNIT_Z.negate());
            sun.setColor(ColorRGBA.White);
            container.addLight(sun);

            GuiGlobals.getInstance().getAnimationState().
                    add(new TweenAnimation(true, Tweens.smoothStep(SpatialTweens.rotate(container.getViewPortNode(), new Quaternion().fromAngleAxis(-FastMath.QUARTER_PI, Vector3f.UNIT_Y), new Quaternion().fromAngleAxis(FastMath.QUARTER_PI, Vector3f.UNIT_Y), 2)),
                            Tweens.smoothStep(SpatialTweens.rotate(container.getViewPortNode(), new Quaternion().fromAngleAxis(FastMath.QUARTER_PI, Vector3f.UNIT_Y), new Quaternion().fromAngleAxis(-FastMath.QUARTER_PI, Vector3f.UNIT_Y), 2))));

//            GuiGlobals.getInstance().getAnimationState().
//                    add(new TweenAnimation(true, (new RotateSpatial(container.getViewPortNode(),
//                            new Quaternion().fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y), 5))));
        }

        if (item != null) {
            if (!spatials.containsKey(item)) {
                Spatial spatial = loadSpatial(item);
                spatials.put(item, spatial);

                //No need when using ViewportPanel  
//                Tween attachTween = Tweens.callTweenMethod(5, this, "inset", (Container) existing, (Container) existing.getChild(0), spatial);
//                GuiGlobals.getInstance().getAnimationState().add(attachTween);
            }

            Spatial spatial = spatials.get(item);
            spatial.removeFromParent();
            ((ViewportPanel) existing).attachScene(spatial);
        } else {
            ((ViewportPanel) existing).getViewPortNode().detachAllChildren();
        }

        return existing;
    }

    public Spatial getSpatial(Item item) {
        return spatials.get(item);
    }

    public Spatial removeSpatial(Item item) {
        return spatials.remove(item);
    }

    protected Spatial loadSpatial(Item item) {
        return ItemLoader.getSpatial(item);
    }

}

I am using ViewportPanel to display jme spatials inside gui elements.

Note, for scrolling I am not using viewport at all, it’s just a Lemur Slider with a GridPanel just like ListBox.

i want create a options menu with scrollpanel
i can´t make work
tanks for the help
can you se my code and what i doing wrong

 package mygame;

    import com.jme3.app.Application;
    import com.jme3.app.state.BaseAppState;
    import com.jme3.math.Vector3f;
    import com.jme3.renderer.ViewPort;
    import com.jme3.scene.Node;
    import com.simsilica.lemur.ActionButton;
    import com.simsilica.lemur.Axis;
    import com.simsilica.lemur.CallMethodAction;
    import com.simsilica.lemur.Container;
    import com.simsilica.lemur.FillMode;
    import com.simsilica.lemur.Insets3f;
    import com.simsilica.lemur.Label;
    import com.simsilica.lemur.Panel;
    import com.simsilica.lemur.PasswordField;
    import com.simsilica.lemur.TabbedPanel;
    import com.simsilica.lemur.TextField;
    import com.simsilica.lemur.component.SpringGridLayout;
    import com.simsilica.lemur.style.ElementId;
    import com.simsilica.lemur.RollupPanel;
    import mygame.panels.ViewportPanel;

    /**
     *
     * @author Pedro Alves
     */
    public class OptionsState  extends BaseAppState  {
        private Container loginPanel;
        private TextField nameField;
        private PasswordField passwordfield;
          private ViewPort  viewPort;
     protected void apply() {
            
           // String name = nameField.getText().trim();
          // String password= passwordfield.getText().trim();
           // if( getState(ConnectionState.class).joinserver(nameField.getText(),passwordfield.getText()) ) {
            //    getStateManager().detach(this);
            //}
        } 
      protected void join() {
            
           // String name = nameField.getText().trim();
          // String password= passwordfield.getText().trim();
           // if( getState(ConnectionState.class).joinserver(nameField.getText(),passwordfield.getText()) ) {
            //    getStateManager().detach(this);
            //}
        } 
     protected void cancel() {
         getStateManager().attach(new MainMenuState());
         getStateManager().detach(this); 
           // String name = nameField.getText().trim();
          // String password= passwordfield.getText().trim();
           // if( getState(ConnectionState.class).joinserver(nameField.getText(),passwordfield.getText()) ) {
            //    getStateManager().detach(this);
            //}
        } 
        public OptionsState() {
        
        }
        @Override
        protected void initialize(Application app) {
          loginPanel = new Container();
            loginPanel.addChild(new Label("Options", new ElementId("title")));
            
            Container props = loginPanel.addChild(new Container(new SpringGridLayout(Axis.Y, Axis.X, FillMode.None, FillMode.Last)));
            props.setBackground(null);    
            TabbedPanel tabs = new TabbedPanel();
            Panel panel1=new Panel(500,200);
            panel1.setInsets(new Insets3f(10, 10, 10, 10));
            ViewportPanel panel= new ViewportPanel(getStateManager(),panel1.getElementId(),panel1.getStyle());
    panel.attachScene(panel1);

    Container tab1 = tabs.addTab("Game Options", new Container());
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));

    tab1.addChild(panel1);

    tab1.addChild(panel);
    Container tab2 = tabs.addTab("Graphic Options", new Container());
    tab2.addChild(new Label("Grapicos options"));
    Container tab3 = tabs.addTab(" Audio Options", new Container());
    tab3.addChild(new Label("Audio"));
    Container tab4 = tabs.addTab("Key Mapping ", new Container());
    tab4.addChild(new Label("Key Mapping"));
     loginPanel.addChild(tabs);

         Container buttons = loginPanel.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
            buttons.setBackground(null);
            buttons.setLayout(new SpringGridLayout(Axis.X, Axis.Y));
           buttons.addChild(new ActionButton(new CallMethodAction("Default", this, "join"))); 
           buttons.addChild(new ActionButton(new CallMethodAction("Reset", this, "join")));
           buttons.addChild(new ActionButton(new CallMethodAction("Apply", this, "join"))); 
             buttons.addChild(new ActionButton(new CallMethodAction("OK", this, "join"))); 
             buttons.addChild(new ActionButton(new CallMethodAction("Cancel", this, "cancel"))); 
            float scale = 1.5f * getState(MainMenuState.class).getStandardScale();
            loginPanel.setLocalScale(scale);
            Vector3f prefs = loginPanel.getPreferredSize().clone();
            prefs.x = Math.max(300, prefs.x);
            loginPanel.setPreferredSize(prefs.clone());
            // Now account for scaling
            prefs.multLocal(scale);
            int width = app.getCamera().getWidth();
            int height = app.getCamera().getHeight();
            loginPanel.setLocalTranslation(width * 0.5f - prefs.x * 0.5f, height * 0.5f + prefs.y * 0.5f, 10);       
        }

        @Override
        protected void cleanup(Application app) {
            
        }

        @Override
        protected void onEnable() {
             Node root = ((Main)getApplication()).getGuiNode();
            root.attachChild(loginPanel);
        }

        @Override
        protected void onDisable() {
            //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        loginPanel.removeFromParent();
        }
        
    }

Sorry I have no time right now, I could not look at your code,

Do not know how to do that,

But instead better way is to break your options to TabbedPanels and RollupPanels

like this

and

ok
when you have time to see my code
or make a simple example how to use viewportpanel

I created a simple example with your code

    import com.jme3.app.Application;
    import com.jme3.app.SimpleApplication;
    import com.jme3.app.state.BaseAppState;
    import com.jme3.math.Vector3f;
    import com.jme3.renderer.ViewPort;
    import com.jme3.scene.Node;
    import com.overthemoon.core.inventory.panel.ViewportPanel;
    import com.overthemoon.core.inventory.panel.ViewportPanel2D;
    import com.simsilica.lemur.ActionButton;
    import com.simsilica.lemur.Axis;
    import com.simsilica.lemur.CallMethodAction;
    import com.simsilica.lemur.Container;
    import com.simsilica.lemur.DefaultRangedValueModel;
    import com.simsilica.lemur.FillMode;
    import com.simsilica.lemur.Insets3f;
    import com.simsilica.lemur.Label;
    import com.simsilica.lemur.Panel;
    import com.simsilica.lemur.PasswordField;
    import com.simsilica.lemur.Slider;
    import com.simsilica.lemur.TabbedPanel;
    import com.simsilica.lemur.TextField;
    import com.simsilica.lemur.component.BorderLayout;
    import com.simsilica.lemur.component.SpringGridLayout;
    import com.simsilica.lemur.core.GuiControl;
    import com.simsilica.lemur.style.ElementId;
    import com.simsilica.lemur.style.Styles;

    /**
     *
     * @author Pedro Alves
     */
    public class OptionsState  extends BaseAppState  {
        private Container loginPanel;
        private TextField nameField;
        private PasswordField passwordfield;
          private ViewPort  viewPort;
     protected void apply() {
            
           // String name = nameField.getText().trim();
          // String password= passwordfield.getText().trim();
           // if( getState(ConnectionState.class).joinserver(nameField.getText(),passwordfield.getText()) ) {
            //    getStateManager().detach(this);
            //}
        } 
      protected void join() {
            
           // String name = nameField.getText().trim();
          // String password= passwordfield.getText().trim();
           // if( getState(ConnectionState.class).joinserver(nameField.getText(),passwordfield.getText()) ) {
            //    getStateManager().detach(this);
            //}
        } 
     protected void cancel() {
         getStateManager().attach(new MainMenuState());
         getStateManager().detach(this); 
           // String name = nameField.getText().trim();
          // String password= passwordfield.getText().trim();
           // if( getState(ConnectionState.class).joinserver(nameField.getText(),passwordfield.getText()) ) {
            //    getStateManager().detach(this);
            //}
        } 
        public OptionsState() {
        
        }
        @Override
        protected void initialize(Application app) {
          loginPanel = new Container();
            loginPanel.addChild(new Label("Options", new ElementId("title")));
            
            Container props = loginPanel.addChild(new Container(new SpringGridLayout(Axis.Y, Axis.X, FillMode.None, FillMode.Last)));
            props.setBackground(null);    
            TabbedPanel tabs = new TabbedPanel();
            Panel panel1=new Panel(500,200);
            panel1.setInsets(new Insets3f(10, 10, 10, 10));
            ViewportPanel panel= new ViewportPanel(getStateManager(),panel1.getElementId(),panel1.getStyle());
    panel.attachScene(panel1);

    Container tab1 = tabs.addTab("Game Options", new Container());
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));
    panel1=tab1.addChild(new Label("Game Options"));

    tab1.addChild(panel1);

    tab1.addChild(panel);
    Container tab2 = tabs.addTab("Graphic Options", new Container());
    tab2.addChild(new Label("Grapicos options"));
    Container tab3 = tabs.addTab(" Audio Options", new Container());
    tab3.addChild(new Label("Audio"));
    Container tab4 = tabs.addTab("Key Mapping ", new Container());
    tab4.addChild(new Label("Key Mapping"));
     loginPanel.addChild(tabs);

         Container buttons = loginPanel.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
            buttons.setBackground(null);
            buttons.setLayout(new SpringGridLayout(Axis.X, Axis.Y));
           buttons.addChild(new ActionButton(new CallMethodAction("Default", this, "join"))); 
           buttons.addChild(new ActionButton(new CallMethodAction("Reset", this, "join")));
           buttons.addChild(new ActionButton(new CallMethodAction("Apply", this, "join"))); 
             buttons.addChild(new ActionButton(new CallMethodAction("OK", this, "join"))); 
             buttons.addChild(new ActionButton(new CallMethodAction("Cancel", this, "cancel"))); 
            float scale = 1.5f * getState(MainMenuState.class).getStandardScale();
            loginPanel.setLocalScale(scale);
            Vector3f prefs = loginPanel.getPreferredSize().clone();
            prefs.x = Math.max(300, prefs.x);
            loginPanel.setPreferredSize(prefs.clone());
            // Now account for scaling
            prefs.multLocal(scale);
            int width = app.getCamera().getWidth();
            int height = app.getCamera().getHeight();
            //loginPanel.setLocalTranslation(width * 0.5f - prefs.x * 0.5f, height * 0.5f + prefs.y * 0.5f, 10);       
        }

        @Override
        protected void cleanup(Application app) {
            
        }

        @Override
        protected void onEnable() {
            ViewportPanel2D viewportPanel = new ViewportPanel2D(getStateManager(), new ElementId(Container.ELEMENT_ID), Styles.ROOT_STYLE);
            viewportPanel.setPreferredSize(new Vector3f(600,400 , 1));
            int width = getApplication().getCamera().getWidth();
            int height = getApplication().getCamera().getHeight();
            viewportPanel.setLocalTranslation((width - 600) / 2, (height + 400) / 2, 100);
            BorderLayout layout = new BorderLayout();
            viewportPanel.getControl(GuiControl.class).setLayout(layout);
            Slider slider_V = new Slider(new DefaultRangedValueModel(), Axis.Y);
            layout.addChild(BorderLayout.Position.East, slider_V);
            
            Slider slider_H = new Slider(new DefaultRangedValueModel(), Axis.X);
            layout.addChild(BorderLayout.Position.South, slider_H);
            
            Node root = ((SimpleApplication)getApplication()).getGuiNode();
            root.attachChild(viewportPanel);
            viewportPanel.attachScene(loginPanel);
            
        }

        @Override
        protected void onDisable() {
            //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        loginPanel.removeFromParent();
        }
        
    }

changed parts :

  • removed :
    //loginPanel.setLocalTranslation(width * 0.5f - prefs.x * 0.5f, height * 0.5f + prefs.y * 0.5f, 10);

added viewport stuff :

protected void onEnable() {
            ViewportPanel2D viewportPanel = new ViewportPanel2D(getStateManager(), new ElementId(Container.ELEMENT_ID), Styles.ROOT_STYLE);
            viewportPanel.setPreferredSize(new Vector3f(600,400 , 1));
            int width = getApplication().getCamera().getWidth();
            int height = getApplication().getCamera().getHeight();
            viewportPanel.setLocalTranslation((width - 600) / 2, (height + 400) / 2, 100);
            BorderLayout layout = new BorderLayout();
            viewportPanel.getControl(GuiControl.class).setLayout(layout);
            Slider slider_V = new Slider(new DefaultRangedValueModel(), Axis.Y);
            layout.addChild(BorderLayout.Position.East, slider_V);
            
            Slider slider_H = new Slider(new DefaultRangedValueModel(), Axis.X);
            layout.addChild(BorderLayout.Position.South, slider_H);
            
            Node root = ((SimpleApplication)getApplication()).getGuiNode();
            root.attachChild(viewportPanel);
            viewportPanel.attachScene(loginPanel);
            
        }
  • Do this yourself :
    Update location of loginPanel by listening to slider changes.
3 Likes

Thanks for the help

1 Like

I trying put the update my contaner when i scroll up our down put i can’t make it work
what i doing wrong

slider_V.getThumbButton().addCommands(Button.ButtonAction.Click.Up, new Command() {
            @Override
            public void execute(Object source) {
                logger.log(Level.INFO, "spinSlider Button UP"); 

            }
        });
        slider_V.getThumbButton().addCommands(Button.ButtonAction.Click.Down, new Command() {
            @Override
            public void execute(Object source) {
                logger.log(Level.INFO, "spinSlider Button Down");
            }
        });