02 Jmonkey3.2.0+Nifty1.4.2实现GUI

作者: 刘开心_8a6c | 来源:发表于2017-11-04 15:08 被阅读14次

    GUI选择

    实现Jmonkey的GUI有三四种方式,我尝试了三种,有

    • Lemur
    • tonegod
    • nifty
      最终选择了Nifty, 因为Lemur用java语法完成,不方便编写,用起来又复杂,读了半天文档也没明白;tonegod的参考资料又少,没看懂;而Nifty可以用xml和java做界面,对于开发过Android的我来说最方便,用起来也灵活,重点是它还开源,github的wiki里有详细的使用说明,用它来做GUI最方便。

    Nifty与Jmonkey的集成

    添加依赖

    在jme中用nifty需要把jme3-niftygui的jar包导入项目,这个maven仓库好像没有,没关系,到jmonkey的sdk里把它复制到项目就行,然后在build.gradle的dependencies中添加:

    compile files('libs/jme3-niftygui-3.2.0-v3.2-prealpha-sdk1-SNAPSHOT.jar') // 写jar包目录和jar包名称
    
    // nifty
    compile "com.github.nifty-gui:nifty:1.4.2"
    compile "com.github.nifty-gui:nifty-style-black:1.4.2"
    compile "com.github.nifty-gui:nifty-default-controls:1.4.2"
    
    新建screens.xml

    Nifty的好处在于可以用xml做显示界面。在resource文件里创建一个文件夹scenes,新建一个xml文件,叫screens.xml。
    之所以叫screens,是因为所有的界面都可以在一个xml文件里,以<screen></screen>标签区分,给screen一个id就能用代码找到它。每一屏是一个screen。切换时通过nifty.gotoScreen("screen id")语句来实现切换。
    xml有很多标签,跟Android一样,通过标签嵌套实现界面,nifty的xml里标签层级如下:

    Nifty标签

    看懂这个图写起来就很容易了,screens.xml示例代码如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <nifty xmlns="http://nifty-gui.lessvoid.com/nifty-gui">
        <useStyles filename="nifty-default-styles.xml"/>
        <useControls filename="nifty-default-controls.xml"/>
        <screen id="start_screen" controller="com.happykai.demo.appstates.StartScreenState">
            <layer id="layer" childLayout="center" backgroundImage="Textures/background.png">
                <panel id="dialog" style="nifty-panel" childLayout="vertical" padding="18px,28px,28px,16px" width="80%"
                       height="70%" align="center" valign="center">
                    <effect>
                        <onStartScreen name="move" timeType="exp" factor="3.5" direction="top" mode="in" length="500"
                                       inherit="true"/>
                        <onEndScreen name="move" timeType="exp" factor="3.5" direction="bottom" mode="out" length="500"
                                     inherit="true"/>
                        <panel id="namePanel" childLayout="horizontal">
                              <text id="name_text" text="你的名字: " width="150px" align="left" textVAlign="center" textHAlign="left" style="nifty-label"/>
                              <control id="name_text_ctl" name="textfield" width="15%" text="300"/>
                        </panel>
                        <panel id="img_btn_panel" childLayout="horizontal">
                               <control id="name_text_ctl" name="button" width="15%" text="300"/>
                              <image id="img" align="right" filename="Textures/add.png" height="20px" width="20px"
                                   visibleToMouse="true">
                                <interact onClick="addDropClick(2)"/>
                              </image>
                        </panel>
                    </effect>
                </panel>
            </layer>
        </screen>
    </nifty>
    

    在nifty中,所有能与用户交互的控件都用<control></control>标签,通过name来区别控件,name是固定字段,有button,textfield,dropdown等,具体可以参考nifty的wiki,里面有每个控件详细的使用说明。

    如果想给一个非control的控件加交互,比如一个image(官方的button很难看,想换成自己想要的button,不妨让美工做一个button,然后直接把图片放过来),在加一个<interact>子标签,如上面例子中的<interact onClick="addDropClick(2)"/>,然后再java中实现该代码即可,括号中的2是传入的参数。

    新建AppState

    从GUI到项目运行场景肯定需要一个场景切换,也是找了好久才找到Jmonkey里每一个场景是一个AppState,配套上nifty,就可以实现场景切换。GUI的AppState给它起名为StartScreenState。

    • 新建StartScreenState.java,继承自AbstractAppState,实现ScreenController接口(实现该接口是为了与xml建立联系,与上面的xml中<screen>标签里的controller对应)。上面例子中的image点击函数addDropClick(2)就写在该java文件中。
    public class StartScreenState extends AbstractAppState implements ScreenController {
        private SimpleApplication app;
        private AssetManager assetManager;
        private InputManager inputManager;
        private ViewPort guiViewPort;
        private AudioRenderer audioRenderer;
        private NiftyJmeDisplay niftyDisplay;
        private Nifty nifty;
        private Screen screen;
    
        @Override
        public void initialize(AppStateManager stateManager,
                               Application app) {
            super.initialize(stateManager, app);
            this.app = (SimpleApplication) app;
            this.assetManager = this.app.getAssetManager();
            this.inputManager = this.app.getInputManager();
            this.guiViewPort = this.app.getGuiViewPort();
            this.audioRenderer = this.app.getAudioRenderer();
    
            this.niftyDisplay = new NiftyJmeDisplay(assetManager,
                    inputManager, audioRenderer, guiViewPort);
            this.nifty = niftyDisplay.getNifty();
            this.nifty.fromXml("Scenes/start_screen.xml",
                    "start", this);
            this.screen = nifty.getScreen("start");
            inputManager.setCursorVisible(true);
            guiViewPort.addProcessor(niftyDisplay);
        }
    
        // 在intellij中该方法会显示没有用过(灰色),没关系,正常
        public void addDropClick(String num) {
              // do something
        }
    
       @Override
        public void bind(@Nonnull Nifty nifty, @Nonnull Screen screen) {
    
        }
    
        @Override
        public void onStartScreen() {
            
        }
    
        @Override
        public void onEndScreen() {
    
        }
    
    }
    

    在该文件里实现对控件的动态控制,比如获得textfield中输入的文字:

    TextField textField = screen.findElementById("ctr_id").getNiftyControl(TextField.class);
    String str = textField .getDisplayedText();
    if (str.isEmpty()){
        JOptionPane.showMessageDialog(
                                null,
                        "输入不能为空",
                                "错误!",
                        JOptionPane.ERROR_MESSAGE);
    }
    

    举一反三,其他诸如button、dropdown的control控制也是如此,先从screen上根据元素id找到元素,然后开始做自己需要的操作。

    用java开发很好的一点就是可以用一切熟悉的java的东西,比如swing里的一些控件,像上例的输入错误框,如果用nifty弹出一个窗口,恐怕又好麻烦,但是用这个就相当简单了。当然jmonkey也可以用swing做图形界面,但是美观什么的就不一定了。

    将AppState添加到Main中

    创建完AppState后就把它加到SimpleApplication中,这是最后一步。

    /**
     * Created by Roman on 2017/10/12.
     */
    public class Main extends SimpleApplication {
    
    
        public static void main(String[] args) throws BackingStoreException {
    //        PrintStream ps= null;
    //        try {
    //            ps = new PrintStream(new FileOutputStream("log.txt"));
    //        } catch (FileNotFoundException e) {
    //            e.printStackTrace();
    //        }
    //        System.setOut(ps);
    
            AppSettings settings = new AppSettings(true);
    
            settings.setTitle("你的名字");
            settings.setVSync(true);
            settings.setWidth(1280);
            settings.setHeight(800);
            Main app = new Main();
            app.setSettings(settings);
            app.setDisplayStatView(false); // 设置状态小窗是否可见
            app.setShowSettings(true); // 设置界面是否显示
            app.setPauseOnLostFocus(false); // 设置程序后台运行,默认为true,即焦点不在程序上则停止显示渲染
            app.start();
        }
        @Override
        public void simpleInitApp() {
            StartScreenState startScreenState = new StartScreenState();
            stateManager.attach(startScreenState);
        }
    
    }
    

    相关文章

      网友评论

        本文标题:02 Jmonkey3.2.0+Nifty1.4.2实现GUI

        本文链接:https://www.haomeiwen.com/subject/udbfmxtx.html