Суббота, 04.05.2024, 20:25
Приветствую Вас Гость

Разработка игр c использованием JPCT

Каталог статей

Главная » Статьи » Разработка игр » JPCT

8. Пользовательский интерфейс: Текстовое поле (GUITextField)
   В данном примере реализации есть ограничения заключающееся в том, что поле предназначено для одно строчного ввода и нельзя переместить каретку в середину текста и начать ввод туда.
   Этот элемент пользовательского интерфейса состоит из 3-х элементов: текст, окантовка, каретка. Изменив которые можно добиватся необходимого результата. Начнем с окантовки, она реализована в классе  GUIBorder вот код:
Код
public class GUIBorder extends GUIElement{
  public int borderDepth;
  private Texture texture;
  private Color color;
  private boolean useTransparent;
   
  public GUIBorder(int x,int y,int heigth,int width,Color color)
  {
  super(x,y,heigth,width);
  borderDepth = 2;
  texture = new Texture(8, 8, color);
  //useTransparent = true;  
  }
   
  public void setTexture(Texture texture)
  {
  this.texture = texture;  
  }

  @Override
  public void evaluteInput(InputMap inputMap) {
   
  }

  @Override
  public void Action() {
   
  }

  @Override
  public void Draw(FrameBuffer buffer) {
  //верхняя линия
  buffer.blit(texture, 0, 0, this.x, this.y, width, borderDepth, useTransparent);
  //правая линия
  buffer.blit(texture, 0, 0, x+width, y, borderDepth, heigth, useTransparent);
  //нижняя линия
  buffer.blit(texture, 0, 0, x, y+heigth-borderDepth, width, borderDepth, useTransparent);
  //левая линия
  buffer.blit(texture, 0, 0, x, y, borderDepth, heigth, useTransparent);
   
  }
   Из кода видно что класс является наследником GUIElement  поэтому в нем реализованы все абстрактные методы, несмотря на то что некоторые из них в данной реализации не нужны. Для отображения рамки создается текстура размером 8х8(создать текстуру меньшего размера мне не удалось т.к. если задать ее меньше 8х8  то текстура будет 256х256) с необходимым цветом, что позволяет избежать необходимости загружать ее с диска.
   Теперь рассмотрим реализацию классов GUITextField и GUICaret, содержащих функционал вывода текста и отображении каретки.

Код

public class GUITextField extends GUIElement{
   
  private GLFont font;
  //private int rowCount;
  private StringBuilder text;  
  private GUICaret caret;  
  private GUIBorder border;
  private boolean isFocus;
   
  private int txt_visible_start=0;
   
  public GUITextField(int x,int y,int heigth,int width)
  {
  super(x,y,heigth,width);  
  // rowCount = 1;
  text = new StringBuilder();
  font = new GLFont(new Font("Times New Roman", 0, 12),GLFont.RUSSIAN+GLFont.ENGLISH);
   
  caret = new GUICaret(x, y, font);
  //добавляем как дочерний элемент;
  this.Add(caret);
  border = new GUIBorder(x, y, heigth, width, Color.GRAY);
  this.Add(border);  
  }

  @Override
  public void evaluteInput(InputMap inputMap) {
  if(getVisible())
  {
  //обрабатываем ввод для дочерних элементов
  for (Object child:this.getChildrens())
  {
  ((GUIElement)child).evaluteInput(inputMap);
  }
   
  int xpos = inputMap.mouse_x;
  int ypos = inputMap.mouse_y;

  if((xpos>=x)&&(xpos<=x+width)&&(ypos>=y)&&(ypos<=y+heigth))
  {  
  if (inputMap.mouse_leftbutton_down)
  {  
  Game.guiManager.setFocusElement(this);
  inputMap.isActionMode = false;
  caret.setVisible(true);
  }
  }  
  if ((!inputMap.isActionMode)&&isFocus)
  {
  this.text.append(inputMap.inputString);
  if (font.getStringBounds(text.toString()).width>width-border.borderDepth)
  {
  txt_visible_start=0;
  String tmp = text.substring(txt_visible_start);
  while(font.getStringBounds(tmp).width>width-border.borderDepth)
  {
  txt_visible_start++;
  tmp = text.substring(txt_visible_start);
  }  
  }
  inputMap.inputString = "";
  caret.setCaretPosition(text.length());  
  }
   
  if (inputMap.backspace&&isFocus)
  {
  if (text.length()!=0)
  {  
  String tmp = text.substring(0, text.length()-1);
  text.delete(0, text.length());
  text.append(tmp);
  }
  inputMap.backspace = false;
  }  
  }
  }

  @Override
  public void Action() {
  throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public void Draw(FrameBuffer buffer) {
   
  String tmp_str;
  if (txt_visible_start>0)
  {
  tmp_str = text.substring(txt_visible_start);
  }
  else
  {
  tmp_str = text.toString();  
  }  
  font.blitString(buffer, tmp_str, x+border.borderDepth+1, y+font.fontHeight, 1, Color.BLACK);
   
  //рисуем связаные элементы
  for(Object child:this.getChildrens())
  {
  ((GUIElement)child).Draw(buffer);
  }
  }
   
  public void setFont(GLFont font)
  {
  this.font = font;  
  }
   
  public void setText(String text)
  {  
  StringBuilder tmp = new StringBuilder(text);  
  this.text = tmp;
  caret.setCaretPosition(text.length());  
  }
   
  @Override
  public void setFocus(boolean isFocus)
  {
  this.isFocus = isFocus;
  caret.setVisible(isFocus);  
  }
   
  private class GUICaret extends GUIElement
  {
  private GLFont font;
  private int caretPos;
  private Texture texture;
  private Timer timer;  
  private boolean cartblit=true;
   
   
  public GUICaret(int x,int y,GLFont font)
  {  
  //инициализируем параметры  
  super (x,y,10,font.fontHeight);
  this.font = font;
   
  texture = new Texture(8, 8, Color.BLACK);  
   
  timer = new Timer(700);
  timer.start();
  setVisible(false);  
  }
   
  @Override
  public void evaluteInput(InputMap inputMap) {
  //если активен для ввода
  if (getFocus())
  {
  this.setVisible(true);
  setCaretPosition(text.length());
  }
  }

  @Override
  public void Action() {  
  }

  @Override
  public void Draw(FrameBuffer buffer) {
  if(this.getVisible())
  {
  if (timer.getElapsedTicks()>0)
  {
  this.cartblit =!this.cartblit;
  }
  if(this.cartblit)
  {
  buffer.blit(texture, 0, 0,this.x+border.borderDepth,this.y, 1, font.getBaseLine()+font.fontHeight/2, false);
  }
  }
  }
  private void setCaretPosition(int pos)
  {
  if (caretPos!=pos)
  {  
  int l;
  if (txt_visible_start>0)
  {
  l = font.getStringBounds(text.substring(txt_visible_start)).width;
  }
  else
  {
  l = font.getStringBounds(text.toString()).width;
  }
  this.x=getParent().x+l;
  caretPos = pos;
  }
  }
  }  
}
   Класс каретки GUICaret является внутренним для GUITextField и они оба унаследованы от GUIElement. В реализации класса основным моментом является организация ввода. Для этого в класс GUIManager была добавлена информация о элементе находящемся в фокусе ввода(функция setFocusElement позволяет корректно обрабатывать эти моменты), а также в класс GUIElement были добавлены поля и методы для хранения информации о том находится ли фокус ввода на них, это позволило унифицировать работу с ними. Также в классе собирающим информацию с устройств ввода InputMap была добавлена информация о режиме работы. Она позволяет определять куда необходимо направлять информацию в текущий фокус элемент или нет. 
   Каретка создается из текстуры черного цвета по такому же принципу как и в классе GUIBorder, эффект моргания достигается использованием Timer c периодом 700 мс.
   Создание текстового поля отличается от создания GUIButton тем, что не происходит перегрузка функции Action, т.к. никаких действий не требуется.
Код

GUITextField tfield = new GUITextField(100, 120, 20, 200);
   
  tfield.setText("Тут");
  guiManager.Add(tfield);
   
  GUITextField tfield2 = new GUITextField(300, 200, 20, 100);  
   
  guiManager.Add(tfield2);

   Технически возможно задать любую реакцию, но необходимо не забыть изменить также обработку в evaluteInput(), например если необходимо добавить реакцию на нажатие клавиши Enter то в функцию необходимо добавить код:
Код
if (inputMap.enter)
{
    Action();
}
  Это все если, что то не понятно задавайте вопросы. 

 

Код примера демонстрирующего создание двух полей находится Доступно только для пользователей
Категория: JPCT | Добавил: Gram01 (01.10.2013) | Автор: Gram01 W
Просмотров: 742 | Теги: GUI jpct, пользовательский интерфейс, текстовое поле, textfield jpct, jpct | Рейтинг: 1.2/4
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа
Категории раздела
JPCT [11]
Раздел о разработке игр на устройства работающие не под управлением Android'а
Сеть [2]
Раздел по вопросам касающимся сетевого взаимодействия приложений на java в контексте разработки игр
Контент [0]
Статьи о работе к контентом при разработки игр
Скрипты [2]
использование скриптов в игровом движке
Разное [1]
различные материалы о разработке игрового движка
Поиск
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
    Copyright Неведомый Р.А. © 2024 | Рейтинг@Mail.ru