Графическое поле ввода
от vl@volk
Возьмем проще, что нам надо для того, чтоб сделать подобный трюк?
1. Смена дисплеев — Canvas-TextBox
2. Обработка команды для TextBox
3. Класс для курсора
4. Класс для графического поля ввода
Начнем с класса для поля ввода. Назовем его GInput.java
Текст будем устанавливать обращаясь напрямую к переменной text. Почему? Для простоты кода.
Теперь сделаем класс курсора. Целый класс нам нужен чтоб в дальнейшем можно было добавить плавное перемещение и ускорение курсора. Ну, а я сделаю просто — буду изменять только позицию на 1. Ну и если будет сенсорный экран будем выключать отображение курсора поскольку здесь нам его отображение будет не нужно.
Методы самодокументированы, и если перевести слова то станет понятно что они делают. Да-да знание английского хотя бы на уровне знания значений слово должно быть. Сразу делаем наше приложение для интернационального распостранения.
Приступим к первому пункту. Для этого нам надо создать два класса Main.java MyCanvas.java
Начнем с Main. Это будет наш стартовый класс. Тут по ходу все ясно и почти никак не относится к теме статьи, упомяну лишь то что здесь мы добавим метод для смены дисплея.
Отрисовка довольно таки интересный процесс, вы видели что я вызываю у каждого объекта метод paint? Это для того чтобы они все появились у нас на экране. Обратите внимание на порядок рисования, всегда рисуйте объекты так как бы они расположены были расположены в жизни, чтобы один объект не перекрывал другой если он этого не должен делать. Например бумага лежит под ручкой соответственно бумагу надо нарисовать первой, а потом ручку.
Почему при обработке нажатия на сенсор я сделал проверку после того как пользователь отпустить палец от экрана? Если мы сделаем по первому нажатию, то оно очень быстро сменится на ввод и это будет не красиво. С кнопками я думаю все понятно? Если нет — спросите.
По мере накопления опыта вы увидите как что-то улучшить, упростить. Сделать так как Вам надо. Например, если присмотреться, то у каждого класса который мы рисуем, есть повторяющиеся переменные, методы. Думаете стоит добавить абстрактный класс и наследовать их от него? А потом еще если объектов много совать в массив или вектор их и зная что у них у всех есть точно метод для рисования (абстрактный метод родителя или метод интерфейса). Да еще и приоритеты можно добавить!
Думайте сами, пишите, делайте по-своему, проверяйте каждый возможный вариант! Да и задавайте вопросы — будьте умнее!
1. Смена дисплеев — Canvas-TextBox
2. Обработка команды для TextBox
3. Класс для курсора
4. Класс для графического поля ввода
Начнем с класса для поля ввода. Назовем его GInput.java
- //GInput.java
- import // упускаю, это азы и каждый должен сам уметь это делать
- public class GInput {
- public int x, y, //точка расположения поля на дисплее
- width, height; // размеры (ширина, высота)
- public String text = "Нажми для ввода"; // текст поля
- public GInput(int x, int y, int width, int height) {
- this.x = x ;
- this.y = y;
- this.width = width;
- this.height = height;
- }
- //рисование поля, нарисуем рамку и внутри пусть будет текст (можешь здесь что угодно нарисовать)
- public void paint(Graphics g) {
- g.setColor(0xffffff);
- g.drawRect(x, y, width,height);
- g.setColor(0x0000ff);
- g.drawString(text, x+1, y+1, Graphics.TOP | Graphics.CENTER);
- }
- // добавим метод для проверки столкновения (принадлежности) точки с(к) полем
- public boolean collide(int x, int y) {
- if (x >= this.x || x <= this.x+width) {
- if (y >= this.y || y <= this.y+height) {
- return true;
- }
- }
- return false;
- }
- }
Теперь сделаем класс курсора. Целый класс нам нужен чтоб в дальнейшем можно было добавить плавное перемещение и ускорение курсора. Ну, а я сделаю просто — буду изменять только позицию на 1. Ну и если будет сенсорный экран будем выключать отображение курсора поскольку здесь нам его отображение будет не нужно.
- //Cursor.java
- public class Cursor {
- public int x, y; // положение
- boolean isEnabled = true; // показывать курсор?
- public Сursor() {
- }
- public void moveLeft() {
- move(1, 0);
- }
- public void moveRight() {
- move(-1, 0);
- }
- public void moveUp() {
- move(0, -1);
- }
- public void moveLeft() {
- move(0, 1);
- }
- // двигаем, изменяя координату на определенное значение onX и onY
- public void move(int onX, int onY) {
- x += onX;
- y += onY;
- }
- // Нарисуем наш курсор (можно и картинку прицепить, но это уже ваше дело.
- public void paint (Graphics g) {
- if(!isEnabled) return; // делаем выход из метода и все
- g.setColor(0xff0000);
- g.drawLine(x-5, y, x+5, y);
- g.drawLine(x, y-5, x, y+5);
- }
- }
Приступим к первому пункту. Для этого нам надо создать два класса Main.java MyCanvas.java
Начнем с Main. Это будет наш стартовый класс. Тут по ходу все ясно и почти никак не относится к теме статьи, упомяну лишь то что здесь мы добавим метод для смены дисплея.
- //Main.java
- public class Main extends MIDlet implements CommandListener {
- public Display display;
- public MyCanvas canvas;
- public TextBox textBox;
- public Displayable currDisplay; // класс для хранения текущего элемента который виден на экране
- private Command commandOk, commandBack;
- public Main() {
- display = Display.getDisplay(this);
- commandOk = new Command("Ok", Command.OK, 0);
- commandBack = new Command("Back", Command.BACK, 1);
- }
- public void startApp() {
- if (currDisplay == null) {
- canvas = new MyCanvas(this);
- textBox = new TextBox();
- textBox.addCommand(commandOk);
- textBox.addCommand(commandBack);
- textBox.setCommandListener(this);
- currDisplay = canvas;
- display.setCurrent(currDisplay);
- canvas.repaint();
- }
- display.setCurrent(currDisplay);
- }
- public void pauseApp() {
- }
- public void destroyApp(boolean unconditional) {
- }
- // смена текущего дисплея, по контексту все понятно
- public void setDisplayable(Displayable d) {
- if (!display.getCurrent().equals(d)) {
- display.setCurrent(d);
- }
- }
- // а вот и обработка наших команд, причем типичная. Если сработала команда Ок ставим текстовому полю зачение и отображаем канвас
- public void commandAction(Command c, Displayable d) {
- if (d.equals(textBox)) {
- if (c == commandOk) {
- canvas.input.text = textBox.getString();
- setDisplayable(canvas);
- } else if (c == commandBack) {
- setDisplayable(canvas);
- }
- }
- }
- //MyCanvas.java — там где будем рисовать
- public class MyCanvas extends Canvas {
- public GInput input; // знаем что это такое
- public Cursor cursor; // знаем
- public Main main; // а эта переменная нам нужна для смены экрана при нажатии на поле ввода
- public MyCanvas (Main main) {
- super();
- setFullScreenMode(true);
- input = new GInput(5, 5, getWidth()-5, getHeight()-5);
- cursor = new Cursor();
- if (hasPointerEvents()) {
- cursor.isEnabled = false;
- }
- this.main = main;
- repaint();
- }
- public void showNotify() {
- repaint();
- }
- // наконец-то одна из интересных штук которая есть в коде. Объяснение под кодом
- public void paint(Graphics g) {
- g.setColor(0);
- g.fillRect(0, 0, getWidth(), getHeigth());
- input.paint(g);
- cursor.paint(g);
- }
- // и второе интересное — обработка нажатий, начнем с сенсора
- public void pointerReleased(int x, int y) {
- if (input.collide(x, y)) {
- main.textBox.setString(""); // очистим TextBox
- main.setDisplay(main.textBox);
- }
- }
- // кнопки
- public void keyPressed(int keyCode) {
- int gameAction = getGameAction(keyCode);
- switch(gameAction) {
- case Canvas.KEY_NUM2:
- case Canvas.UP:
- cursor.moveUp();
- break;
- case Canvas.KEY_NUM8:
- case Canvas.DOWN:
- cursor.moveDown();
- break;
- case Canvas.KEY_NUM4:
- case Canvas.LEFT:
- cursor.moveLeft();
- break;
- case Canvas.KEY_NUM6:
- case Canvas.Right:
- cursor.moveRight();
- break;
- case Canvas.KEY_NUM5:
- case Canvas.FIRE:
- if (input.collide(cursor.x, cursor.y)) {
- main.textBox.setString(""); // очистим TextBox
- main.setDisplay(main.textBox);
- }
- break;
- }
- repaint();
- }
- }
Почему при обработке нажатия на сенсор я сделал проверку после того как пользователь отпустить палец от экрана? Если мы сделаем по первому нажатию, то оно очень быстро сменится на ввод и это будет не красиво. С кнопками я думаю все понятно? Если нет — спросите.
По мере накопления опыта вы увидите как что-то улучшить, упростить. Сделать так как Вам надо. Например, если присмотреться, то у каждого класса который мы рисуем, есть повторяющиеся переменные, методы. Думаете стоит добавить абстрактный класс и наследовать их от него? А потом еще если объектов много совать в массив или вектор их и зная что у них у всех есть точно метод для рисования (абстрактный метод родителя или метод интерфейса). Да еще и приоритеты можно добавить!
Думайте сами, пишите, делайте по-своему, проверяйте каждый возможный вариант! Да и задавайте вопросы — будьте умнее!