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里标签层级如下:

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中,所有能与用户交互的控件都用标签,通过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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值