02 Jmonkey3.2.0+Nifty1.4.2实现GUI

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一个id就能用代码找到它。每一屏是一个screen。切换时通过nifty.gotoScreen(“screen id”)语句来实现切换。 xml有很多标签,跟Android一样,通过标签嵌套实现界面,nifty的xml里标签层级如下:

看懂这个图写起来就很容易了,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中,所有能与用户交互的控件都用标签,通过name来区别控件,name是固定字段,有button,textfield,dropdown等,具体可以参考nifty的wiki,里面有每个控件详细的使用说明。

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

新建AppState

从GUI到项目运行场景肯定需要一个场景切换,也是找了好久才找到Jmonkey里每一个场景是一个AppState,配套上nifty,就可以实现场景切换。GUI的AppState给它起名为StartScreenState。 - 新建StartScreenState.java,继承自AbstractAppState,实现ScreenController接口(实现该接口是为了与xml建立联系,与上面的xml中标签里的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);
    }

}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Young Dreamer

html5之histroy浅析

history是HTML5的新特性,我们可以使用它操作这个历史记录堆栈。 (1)history提供了对浏览器历史纪录堆栈的读取,同时实现在访问记录中的前进和后退...

2147
来自专栏debugeeker的专栏

xss渗透试验(2)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

681
来自专栏7号代码

Android应用界面开发——Widget(实现液晶时钟)

桌面控件是通过BroadcastReceiver的形式进行控制的,因此每个桌面控件都对应于一个BroadcastReceiver。开发桌面控件时,只需继承Bro...

2576
来自专栏木子墨的前端日常

react-navigation 使用笔记 持续更新中

React-Navigation是目前React-Native官方推荐的导航组件,代替了原用的Navigator。最近开始接触,做个笔记

1224
来自专栏老马寒门IT

jQuery EasyUI 详解

easyui 为创建现代化,互动,JavaScript 应用程序,提供必要的功能。

4671
来自专栏web开发

移动端图片放大滑动查看-插件photoswipe的使用

最近在开发项目的时候,遇到一个需求,需要移动端实现放大查看图片的功能,然后我就在网上搜索了一下资料,看到了photoswipe这个插件,后来试了试,确实挺好用的...

8845
来自专栏强仔仔

利用js实现输入框动态提示信息

为了提高和用户的交互性,现在的输入框往往都采用输入信息自动提示的功能,类似于百度输入框中的提示功能。 设计思路是:在输入框input的组件下面放置一个div,这...

6916
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(32)-swfupload多文件上传[附源码]

文件上传这东西说到底有时候很痛,原来的asp.net服务器控件提供了很简单的上传,但是有回传,还没有进度条提示。这次我们演示利用swfupload多文件上传,项...

28510
来自专栏debugeeker的专栏

xss渗透试验(3)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

901
来自专栏施炯的IoT开发专栏

《101 Windows Phone 7 Apps》读书笔记-TODO LIST

课程内容 ØPivot控件 ØContext Menu ØData Contract Attributes     TODO List使得我们能够快速、简单并...

1756

扫码关注云+社区

领取腾讯云代金券