Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            Документация для продвинутых пользователей
                Взаимодействие с GUI в Java

Взаимодействие с GUI в Java

Опубликованно: 20.08.2017, 21:06
Последняя редакция, Andry: 22.08.2017 17:31
  1. Концепция Nifty GUI
  2. Nifty GUI Рекомендации
  3. Nifty GUI XML Компоновка или Nifty GUI Java Компоновка
  4. Nifty GUI Накладывается или Nifty GUI Проецируется
  5. Nifty GUI Java Взаимодействие
  6. В предыдущих уроках вы создали двухэкранный пользовательский интерфейс. Но он все еще статичен, и когда вы нажимаете кнопки, ничего не происходит. Предназначение GUI является общение с вашими Java-классами: Ваша игра должна знать, куда пользователи щелкнули, какие настройки они выбрали, какие значения они ввели в текстовое поле и.т.д. . Точно так же и пользователь должен знать, состояние игры когда он играет (Очки, здоровье и.т.д.).

    Подключить GUI к Java-контроллеру

    Чтобы позволить Nifty экрану взаимодействовать с приложением Java, вы регистрируете ScreenController на каждом NiftyGUI экране. Вы создаете ScreenController, создавая Java класс, который реализует интерфейс de.lessvoid.nifty.screen.ScreenController и его абстрактные методы.

    Создайте AppState файл MyStartScreen.java в своем пакете. (Кликнув [ПК Мыши] на вашем пакете ▸ Новый ▸ Другое … ▸ JME3 Classes ▸ New AppState)

    Поскольку вы пишете jME3 приложение, вы можете дополнительно сделать класс ScreenController расширением класса AbstractAppState! Это дает ScreenController доступ к объекту приложения и циклу обновления!

    Теперь добавьте implements ScreenController в public class MyStartScreen extends AbstractAppState{ и добавляет import de.lessvoid.nifty.screen.ScreenController;

    Продолжайте добавлять:

    import de.lessvoid.nifty.screen.Screen;
    
    ...
    
    public void bind(Nifty nifty, Screen screen) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    public void onStartScreen() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    public void onEndScreen() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    /*
     * Чтобы изменить этот шаблон, выберите Сервис | Шаблоны
     * и откройте шаблон в редакторе.
     */
    package mygame;
    
    import com.jme3.app.Application;
    import com.jme3.app.state.AbstractAppState;
    import com.jme3.app.state.AppStateManager;
    import de.lessvoid.nifty.Nifty;
    import de.lessvoid.nifty.screen.Screen;
    import de.lessvoid.nifty.screen.ScreenController;
    
    public class MyStartScreen extends AbstractAppState implements ScreenController {
    
        @Override
        public void initialize(AppStateManager stateManager, Application app) {
            super.initialize(stateManager, app);
            //TODO: инициализация вашего AppState, например присоединением spatials к rootNode
            //это вызывается в потоке OpenGL после присоединения AppState
        }
    
        @Override
        public void update(float tpf) {
            //TODO: реализовать поведение во время выполнения
        }
    
        @Override
        public void cleanup() {
            super.cleanup();
            //TODO: Очистить то, что вы инициализировали в методе инициализации,
            //например удалить все spatials из rootNode
            //это вызывается в потоке OpenGL после присоединения AppState
        }
    
        public void bind(Nifty nifty, Screen screen) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    
        public void onStartScreen() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    
        public void onEndScreen() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    Название и пакет вашего пользовательского класса ScreenController (здесь mygame.MyStartScreen) входят в параметр контроллера соответствующего XML-экрана, к которому они принадлежат. Например:

    <nifty>
      <screen id="start" controller="mygame.MyStartScreen">
          <!-- код панелей и слоёв ... -->
      </screen>
    </nifty>

    И то же самое в синтаксисе Java:

      nifty.addScreen("start", new ScreenBuilder("start") {{
          controller(new mygame.MyStartScreen())}});

    Теперь подключены Java-класс MyStartScreen и этот GUI экран (start). В этом примере вы также можете подключить hud экран к MyStartScreen.

    Сделаем взаимодействие между GUI и Java

    В большинстве случаев вам нужно будет передавать игровые данные в ScreenController и из него. Обратите внимание, что вы можете передать любые пользовательские аргументы из вашего Java-класса в конструктор своего ScreenController (public MyStartScreen(GameData data) {}).

    Используйте любую комбинацию из трех следующих способов, чтобы заставить Java-классы взаимодействовать с GUI.

    GUI вызывает метод Void Java

    Это то, как вы реагируете на взаимодействие с GUI, например, клики в XML GUI:

    1. Добавите visibleToMouse=“true для родительского элемента!
    2. Встроите элемент <interact /> в родительский элемент.
    3. Укажите Java методы которые вы хотите вызвать когда выполняете некоторые действия, такие как клик мыши. +Пример: <interact onClick=“startGame(hud) />

    Или это то, как вы реагируете на взаимодействие с GUI, такое как клики в Java GUI:

    1. Добавите visibleToMouse(true); для родительского элемента!
    2. Встроите элемент interact…() в родительский элемент
    3. Укажите Java методы которые вы хотите вызвать когда выполняете некоторые действия. +Пример: interactOnClick(“startGame(hud));

    В следующем примере мы вызываем метод startGame(), когда игрок нажимает кнопку [Start] и quitGame(), когда игрок нажимает кнопку [Quit].

            <panel id="panel_bottom_left" height="50%" width="50%" valign="center" childLayout="center">
              <control name="button" label="Start" id="StartButton" align="center" valign="center"
              visibleToMouse="true" >
                <interact onClick="startGame(hud)"/>
              </control>
            </panel>
    
            <panel id="panel_bottom_right" height="50%" width="50%" valign="center" childLayout="center">
              <control name="button" label="Quit" id="QuitButton" align="center" valign="center"
              visibleToMouse="true" >
                <interact onClick="quitGame()"/>
              </control>
            </panel>

    И то же самое в синтаксисе Java:

    control(new ButtonBuilder("StartButton", "Start") {{
      alignCenter();
      valignCenter();
      height("50%");
      width("50%");
      visibleToMouse(true);
      interactOnClick("startGame(hud)");
    }});
    ...
    
    control(new ButtonBuilder("QuitButton", "Quit") {{
      alignCenter();
      valignCenter();
      height("50%");
      width("50%");
      visibleToMouse(true);
      interactOnClick("quitGame()");
    }});

    Вернемся в класс MyStartScreen, вы указываете, что делают методы startGame() и quitGame(). Как вы видите, вы можете передать String аргументы (здесь в hud) в вызове метода. Вы также видите, что у вас есть доступ к объекту app.

    public class MyStartScreen implements ScreenController {
      ...
    
      /** пользовательские методы */
      public void startGame(String nextScreen) {
        nifty.gotoScreen(nextScreen);  // переключиться на другой экран
        // запустите игру и сделайте еще что-нибудь...
      }
    
      public void quitGame() {
        app.stop();
      }
    
      ...
    }

    Пример startGame() просто переключает GUI на экран hud, когда пользователь нажимает кнопку [Start]. Конечно, в реальной игре вы бы выполнили больше шагов: загрузка игрового уровня, переключение на вход в игру и настройки управления, установка пользовательского запуска с помощью boolean в true, добавление пользовательских внутриигровых AppStates и многое другое.

    Пример quitGame() показывает, что у вас есть доступ к объекту приложения app, потому что вы сделали ScreenController расширением AbstractAppState. (Если вы создаете код из этого примера, обратите внимание, что вам нужно убедиться, что app инициализировано, прежде чем вы сможете успешно вызвать его методы.)

    GUI получает значение возвращаемое из Java-метода

    Когда Nifty GUI инициализируется, вы можете получать данные из Java. В этом примере Java класс getPlayerName() в MyStartScreen определяет Текст, который отображается в текстовом поле перед словами ‘s Cool Game.

    Сначала определите Java метод в экранном контроллере, в этом примере getPlayerNam().

    public class MySettingsScreen implements ScreenController {
      ...
      public String getPlayerName(){
        return System.getProperty("user.name");
      }
    }

    Nifty использует ${CALL.getPlayerName()}, чтобы получить значение возвращаемое методом getPlayerName() из вашего Java класса ScreenController.

    <text text="${CALL.getPlayerName()}'s Cool Game" font="Interface/Fonts/Default.fnt" width="100%" height="100%" />

    И то же самое в синтаксисе Java:

    text(new TextBuilder() {{
      text("${CALL.getPlayerName()}'s Cool Game");
      font("Interface/Fonts/Default.fnt");
      height("100%");
      width("100%");
    }});

    Вы можете использовать это для строковых и числовых значений (например, когда вы считываете настройки из файла, вы показываете результаты в GUI), а также для методов с побочными эффектами.

    Java изменяет элементы и события

    Вы также можете изменять внешний вид и функции ваших nifty элементов в Java. Убедитесь, что элемент, который вы хотите изменить, имеет свой идентификатор атрибута id=“name, который поможет вам идентифицировать его и задать его.

    Вот пример того, как изменить изображение под названием playerhealth:

    // загрузка или создание нового изображения
    NiftyImage img = nifty.getRenderEngine().createImage("Interface/Images/face2.png", false);
    // поиск старого
    Element niftyElement = nifty.getCurrentScreen().findElementByName("playerhealth");
    // поменяем старое на новое
    niftyElement.getRenderer(ImageRenderer.class).setImage(img);

    То же самое справедливо и для других элементов, например текстовой метки «score:

    // найдем старый текст
    Element niftyElement = nifty.getCurrentScreen().findElementByName("score");
    // поменяем старый на новый текст
    niftyElement.getRenderer(TextRenderer.class).setText("124");

    Аналогично, чтобы изменить для элемента событие onClick(), создайте объект ElementInteraction:

    Element niftyElement = nifty.getCurrentScreen().findElementByName("myElement");
    niftyElement.getElementInteraction().getPrimary().setOnMouseOver(new NiftyMethodInvoker(nifty, "myCustomMethod()", this));

    Чтобы это работало, в вашем элементе xml уже должен быть (возможно, неактивный) тег <interactive />:

    <interact onClick="doNothing()"/>

    Следующие шаги


    Переведено для jmonkeyengine.ru, оригинал
    Автор перевода: Andry

    Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.