Графическое поле ввода

от
Java    java me, gamedev

Возьмем проще, что нам надо для того, чтоб сделать подобный трюк?
1. Смена дисплеев — Canvas-TextBox
2. Обработка команды для TextBox
3. Класс для курсора
4. Класс для графического поля ввода


     Начнем с класса для поля ввода. Назовем его GInput.java
  1. //GInput.java
  2. import // упускаю, это азы и каждый должен сам уметь это делать
  3.  
  4. public class GInput {
  5.  
  6.   public int x, y, //точка расположения поля на дисплее
  7.                   width, height; // размеры (ширина, высота)
  8.  
  9.   public String text = "Нажми для ввода"; // текст поля
  10.  
  11.   public GInput(int x, int y, int width, int height) {
  12.     this.x = x ;
  13.     this.y = y;
  14.     this.width = width;
  15.     this.height = height;
  16.   }
  17.  
  18.   //рисование поля, нарисуем рамку и внутри пусть будет текст (можешь здесь что угодно нарисовать)
  19.   public void paint(Graphics g) {
  20.     g.setColor(0xffffff);
  21.     g.drawRect(x, y, width,height);
  22.     g.setColor(0x0000ff);
  23.     g.drawString(text, x+1, y+1, Graphics.TOP | Graphics.CENTER);
  24.   }
  25.  
  26.   // добавим метод для проверки столкновения (принадлежности) точки с(к) полем
  27.   public boolean collide(int x, int y) {
  28.     if (x >= this.x || x <= this.x+width) {
  29.       if (y >= this.y || y <= this.y+height) {
  30.         return true;
  31.       }
  32.     }
  33.     return false;
  34.   }
  35. }
     Текст будем устанавливать обращаясь напрямую к переменной text. Почему? Для простоты кода.

     Теперь сделаем класс курсора. Целый класс нам нужен чтоб в дальнейшем можно было добавить плавное перемещение и ускорение курсора. Ну, а я сделаю просто — буду изменять только позицию на 1. Ну и если будет сенсорный экран будем выключать отображение курсора поскольку здесь нам его отображение будет не нужно.
  1. //Cursor.java
  2.  
  3. public class Cursor {
  4.  
  5.   public int x, y; // положение
  6.   boolean isEnabled = true; // показывать курсор?
  7.  
  8.   public Сursor() {
  9.   }
  10.  
  11.   public void moveLeft() {
  12.     move(1, 0);
  13.   }
  14.  
  15.   public void moveRight() {
  16.     move(-1, 0);
  17.   }
  18.  
  19.   public void moveUp() {
  20.     move(0, -1);
  21.   }
  22.  
  23.   public void moveLeft() {
  24.     move(0, 1);
  25.   }
  26.  
  27.   // двигаем, изменяя координату на определенное значение onX и onY
  28.   public void move(int onX, int onY) {
  29.     x += onX;
  30.     y += onY;
  31.   }
  32.  
  33.   // Нарисуем наш курсор (можно и картинку прицепить, но это уже ваше дело.
  34.   public void paint (Graphics g) {
  35.     if(!isEnabled) return; // делаем выход из метода и все
  36.     g.setColor(0xff0000);
  37.     g.drawLine(x-5, y, x+5, y);
  38.     g.drawLine(x, y-5, x, y+5);
  39.   }
  40. }
     Методы самодокументированы, и если перевести слова то станет понятно что они делают. Да-да знание английского хотя бы на уровне знания значений слово должно быть. Сразу делаем наше приложение для интернационального распостранения.

     Приступим к первому пункту. Для этого нам надо создать два класса Main.java MyCanvas.java
Начнем с Main. Это будет наш стартовый класс. Тут по ходу все ясно и почти никак не относится к теме статьи, упомяну лишь то что здесь мы добавим метод для смены дисплея.
  1. //Main.java
  2.  
  3. public class Main extends MIDlet implements CommandListener {
  4.  
  5.   public Display display;
  6.   public MyCanvas canvas;
  7.   public TextBox textBox;
  8.   public Displayable currDisplay; // класс для хранения текущего элемента который виден на экране
  9.  
  10.   private Command commandOk, commandBack;
  11.  
  12.   public Main() {
  13.     display = Display.getDisplay(this);
  14.     commandOk = new Command("Ok", Command.OK, 0);
  15.     commandBack = new Command("Back", Command.BACK, 1);
  16.   }
  17.  
  18.   public void startApp() {
  19.     if (currDisplay == null) {
  20.       canvas = new MyCanvas(this);
  21.  
  22.       textBox = new TextBox();
  23.       textBox.addCommand(commandOk);
  24.       textBox.addCommand(commandBack);
  25.       textBox.setCommandListener(this);
  26.  
  27.       currDisplay = canvas;
  28.       display.setCurrent(currDisplay);
  29.       canvas.repaint();
  30.     }
  31.     display.setCurrent(currDisplay);
  32. }
  33.  
  34.   public void pauseApp() {
  35.   }
  36.  
  37.   public void destroyApp(boolean unconditional) {
  38.   }
  39.  
  40.   // смена текущего дисплея, по контексту все понятно
  41.   public void setDisplayable(Displayable d) {
  42.     if (!display.getCurrent().equals(d)) {
  43.       display.setCurrent(d);
  44.     }
  45.   }
  46.  
  47.   // а вот и обработка наших команд, причем типичная. Если сработала команда Ок ставим текстовому полю зачение и отображаем канвас
  48.   public void commandAction(Command c, Displayable d) {
  49.     if (d.equals(textBox)) {
  50.       if (c == commandOk) {
  51.         canvas.input.text = textBox.getString();
  52.         setDisplayable(canvas);
  53.       } else if (c == commandBack) {
  54.         setDisplayable(canvas);
  55.       }
  56.     }
  57.   }
  1. //MyCanvas.java — там где будем рисовать
  2.  
  3. public class MyCanvas extends Canvas {
  4.  
  5.   public GInput input; // знаем что это такое
  6.   public Cursor cursor; // знаем
  7.  
  8.   public Main main; // а эта переменная нам нужна для смены экрана при нажатии на поле ввода
  9.  
  10.   public MyCanvas (Main main) {
  11.     super();
  12.     setFullScreenMode(true);
  13.     input = new GInput(5, 5, getWidth()-5, getHeight()-5);
  14.     cursor = new Cursor();
  15.     if (hasPointerEvents()) {
  16.       cursor.isEnabled = false;
  17.     }
  18.     this.main = main;
  19.     repaint();
  20.   }
  21.  
  22.   public void showNotify() {
  23.     repaint();
  24.   }
  25.  
  26.   // наконец-то одна из интересных штук которая есть в коде. Объяснение под кодом
  27.   public void paint(Graphics g) {
  28.     g.setColor(0);
  29.     g.fillRect(0, 0, getWidth(), getHeigth());
  30.     input.paint(g);
  31.     cursor.paint(g);
  32.   }
  33.  
  34.   // и второе интересное — обработка нажатий, начнем с сенсора
  35.   public void pointerReleased(int x, int y) {
  36.     if (input.collide(x, y)) {
  37.       main.textBox.setString(""); // очистим TextBox
  38.       main.setDisplay(main.textBox);
  39.     }
  40.   }
  41.  
  42.  // кнопки
  43.   public void keyPressed(int keyCode) {
  44.     int gameAction = getGameAction(keyCode);
  45.  
  46.     switch(gameAction) {
  47.       case Canvas.KEY_NUM2:
  48.       case Canvas.UP:
  49.         cursor.moveUp();
  50.       break;
  51.       case Canvas.KEY_NUM8:
  52.       case Canvas.DOWN:
  53.         cursor.moveDown();
  54.       break;
  55.       case Canvas.KEY_NUM4:
  56.       case Canvas.LEFT:
  57.         cursor.moveLeft();
  58.       break;
  59.       case Canvas.KEY_NUM6:
  60.       case Canvas.Right:
  61.         cursor.moveRight();
  62.       break;
  63.       case Canvas.KEY_NUM5:
  64.       case Canvas.FIRE:
  65.         if (input.collide(cursor.x, cursor.y)) {
  66.            main.textBox.setString(""); // очистим TextBox
  67.            main.setDisplay(main.textBox);
  68.         }
  69.       break;
  70.     }
  71.  
  72.     repaint();
  73.   }
  74.  
  75. }
     Отрисовка довольно таки интересный процесс, вы видели что я вызываю у каждого объекта метод paint? Это для того чтобы они все появились у нас на экране. Обратите внимание на порядок рисования, всегда рисуйте объекты так как бы они расположены были расположены в жизни, чтобы один объект не перекрывал другой если он этого не должен делать. Например бумага лежит под ручкой соответственно бумагу надо нарисовать первой, а потом ручку.
     Почему при обработке нажатия на сенсор я сделал проверку после того как пользователь отпустить палец от экрана? Если мы сделаем по первому нажатию, то оно очень быстро сменится на ввод и это будет не красиво. С кнопками я думаю все понятно? Если нет — спросите.

     По мере накопления опыта вы увидите как что-то улучшить, упростить. Сделать так как Вам надо. Например, если присмотреться, то у каждого класса который мы рисуем, есть повторяющиеся переменные, методы. Думаете стоит добавить абстрактный класс и наследовать их от него? А потом еще если объектов много совать в массив или вектор их и зная что у них у всех есть точно метод для рисования (абстрактный метод родителя или метод интерфейса). Да еще и приоритеты можно добавить!
     Думайте сами, пишите, делайте по-своему, проверяйте каждый возможный вариант! Да и задавайте вопросы — будьте умнее!
  • +6
  • views 4854