Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java ME (J2ME) > Урок по созданию графического меню


Автор: Samuil 16.7.2006, 10:54
Hi All!!!
Многие сталкиваются при написании игр на проблемму с меню(решенить эту проблемму можно решить двумя способами: 1)Создание с помощью высокоуровнего интерфейса 2)Создание с помощью низкоуровнего интерфейса).

Вот решил написать урок по созданию графического меню с помощью класса низкоуровнего интерфейса.
В коде выложенны два класса Menu (MIDlet) и класс mendraw (Canvas), В классе mendraw в методе paint() , рисуется 3 прямоуголика, когда переменная индекс равна номеру прямоугольника то прямоугольник заливается указанным цветом! А вот и код:

Код

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class Menu extends MIDlet {

  private Display display;
  mendraw m = new mendraw(); //Создание подкласса mendraw
  int index = 1; // Индекс выделенной кнопочки
  int heightScreen, widthScreen; // Берут разрешение экрана
  int xPosition = 50; // Позиция "x" рисования меню
  int yPosition = 30; // Позиция "y" рисования меню

  public void startApp() {
    display = Display.getDisplay(this);
    display.setCurrent(m); // Сразу после загрузки мидлета переходит на класс mendraw
  }

  public void pauseApp() {}

  public void destroyApp(boolean _boolean) {}

  class mendraw extends Canvas { //Вот и сам класс mendraw

    public void paint(Graphics g) {
      heightScreen = g.getClipHeight(); //Определяем высоту окна
      widthScreen = g.getClipWidth(); //Определяем ширину окна

      g.setColor(255, 255, 255); // Задаем цвет прямоугольника
      g.fillRect(0, 0, 300, 300); //Заливаем прямоугольник

      g.setColor(0, 0, 0); //Задаем цвет прямоугольников меню
      g.drawRect(20, yPosition, 60, 20); // Рисуем первое меню
      g.drawRect(20, yPosition + 30, 60, 20); //Рисуем второе меню
      g.drawRect(20, yPosition + 60, 60, 20); //Рисуем третье меню

      g.setColor(0, 0, 0);
      g.drawString("Menu", xPosition, yPosition + 2, g.TOP | g.HCENTER); // Рисуем первую строку меню
      g.drawString("Menu", xPosition, yPosition + 30 + 2, g.TOP | g.HCENTER); // Рисуем второю строку меню
      g.drawString("Menu", xPosition, yPosition + 60 + 2, g.TOP | g.HCENTER); // Рисуем третью строку меню

      if (index == 1) { // Если индекс равен 1
        g.setColor(0, 0, 100);
        g.fillRect(20, yPosition, 60, 20); //Заливаем прямоугольник №1
        g.setColor(255, 255, 255);
        g.drawString("Menu", xPosition, yPosition, g.TOP | g.HCENTER); // Рисуем первую строку меню
      }
      if (index == 2) { // Если индекс равен 2
        g.setColor(0, 0, 100);
        g.fillRect(20, yPosition + 30, 60, 20); //Заливаем прямоугольник№2
        g.setColor(255, 255, 255);
        g.drawString("Menu", xPosition, yPosition + 30, g.TOP | g.HCENTER); // Рисуем первую строку меню
      }

      if (index == 3) { // Если индекс равен 3
        g.setColor(0, 0, 100);
        g.fillRect(20, yPosition + 60, 60, 20); //Заливаем прямоугольник №3
        g.setColor(255, 255, 255);
        g.drawString("Menu", xPosition, yPosition + 60, g.TOP | g.HCENTER); // Рисуем первую строку меню

      }
    }

    public void keyPressed(int KeyCode) {
      int press = KeyCode; //Заносим в переменную код нажатой кнопки

      if (press == -5) { //Усли нажата кнопка OK
        System.out.println("Вы нажали на кнопочку: " + index);
      }

      if (press == -2) { //Усли нажата кнопка DOWN
        if (index > 2) {
          index = 1;
        }
        else {
          index++; // Перемещаем прямоугольники вниз
        }
        repaint(); //Прорисовываем изменения
      }
      if (press == -1) { //Усли нажата кнопка UP
        if (index < 2) {
          index = 3;
        }
        else {
          index--; // Перемещаем прямоугольники вверх
        }
        repaint(); //Прорисовываем изменения
      }
    }
  }
}

Вместо прямоугольников Вы можете всавлять свои картинки, рисовать овалы, строки и многое другое! Все зависит от Вашего воображения!
Оцените пожалуйста урок.

 

Автор: BackUp 16.7.2006, 11:02
Привет, интересная темка, а пример  с картинками можешь дать? 

Автор: Samuil 16.7.2006, 14:29
Да просто пишешь: 
try{
Image img=Image.createImage("...");
}catch(IOException e){}

public void paint(Graphics g){
g.drawImage(img,x,y,0);
}
И все! Вот у тебя картинка! правда надо в методе KeyPressed() указать про прорисовку рисунка! 

Автор: Samuil 16.7.2006, 14:49
BackUp, А тема то как? Понравилась? 

Автор: Zamuta 18.7.2006, 13:45
Юзайте J2MEPolish, реально красивого меню с нуля тяжело написать, хотя никто не запрещает. Сам давно пользуюсь J2MEPolish очень нравится........советую..... Давно пора развивать эту тему........ 

Автор: W0LF 18.7.2006, 17:55
А разве он не платный? бесплатный он только для freeware... 

Автор: Samuil 18.7.2006, 23:11
Привет! Ну я всего лишь примерчик привел как легко создать графическое меню, а все остальное зависит от вашего воображения! smile  Так что можете дополнять и улучшать smile  

Автор: 02077461 26.7.2006, 10:05
Тема интересная, но реализация, откровенно, слабая.
Меню не гибкое, объект не инкапсулирован. А что делать, если тебе надо в RunTime изменить меню?. 
Понятно, что это простой пример, однако он далеко не лучший. 
P.S. не мешало бы еще узнать о name conversion от разработчиков.  

Автор: Samuil 26.7.2006, 11:50
02077461
Цитата

Тема интересная, но реализация, откровенно, слабая.

Но я и не пытался создать крутое меню с крутой реалицацие smile , Просто мне самому нужно было создать красивое меню и я решил что для начинающих это было бы интересно smile  

Автор: 02077461 26.7.2006, 12:05
Нет, как раз таки это не должно быть интересно. Думаю, что со мной согласяться, что лучше учиться на хороших примерах, нежели на быстрых реализациях.
Не претендую на хороший пример, однако хочу показать как я решал подобную задачу. Прошу не судить строго, это было давно, и подходил сгаряча, без этапа проектирования.
Код

package com.canvas.source.visiel.menu;

import java.util.Vector;

import javax.microedition.lcdui.Graphics;

import com.canvas.source.interfaces.GView;
import com.canvas.source.util.GRectangle;

public class GMenu extends GView implements GMenuListener, Runnable{
    private Vector items;
    private GMenuItem lastRes = null;
    private int currentIndex = 0;
    private Vector menuListener;
    private int itemCount = 0;
    
    private String title = "";
    
    private int bgColor = 0x00000000;
    private int fgColor = 0X00FFFFFF;
    
//     ***********************************************************************
    public GMenu(String title, int x1, int y1, int x2, int y2){
        super(x1,y1,x2,y2);
        this.title = title;
    }
//     ***********************************************************************
    public GMenu(String title){
        super();
        this.title = title;
    }
//     ***********************************************************************
    public GMenuItem createItem(String text, String command){
        GMenuItem item = new GMenuItem(text, command); 
        addItem(item);
        return item;
    }
//     ***********************************************************************
    public GMenuItem createItem(String text){
        GMenuItem item = new GMenuItem(text); 
        addItem(item);
        return item;
    }
//     ***********************************************************************
    protected void init(){
        super.init();
        menuListener = new Vector();
        items = new Vector();
    }
//     ***********************************************************************
    public void hideMenu(){
        setVisible(false);
    }
//     ***********************************************************************
    public void run(){
        // TODO to make it runnable to be able to scroll the titles;
        while (true)
            if (isVisible){
                // do something
            }
    }
//     ***********************************************************************
    public int showMenu(Graphics g, GRectangle r){
        setVisible(true);
        int c = g.getColor();
        g.setColor(bgColor);
        g.fillRect(r.getX(), r.getY(), r.getWidth() , itemCount*15 + 20);//r.getHeight());
        g.setColor(fgColor);
        GMenuItem item;
        GRectangle rect = new GRectangle(0,0,0,0);
        g.drawString(title, r.getX() + 10, r.getY(), 0);
        for (int i=0; i<itemCount; i++){
            item = (GMenuItem)items.elementAt(i);
            rect.set(r.getX()+3, r.getY()+17+i*15, r.getWidth()-6, 14);
            item.drawSelf(g,rect, i==currentIndex);
        }
        g.setColor(c);
        return items.indexOf(lastRes);
    }
//     ***********************************************************************
    public void paint(Graphics g, GRectangle r){
        showMenu(g, r);
    }
//     ***********************************************************************
    public int getChoise(){
        return items.indexOf(lastRes);
    }
//     ***********************************************************************
    public String getChoiseCommand(){
        if (lastRes == null) return "";
        return lastRes.getCommand();
    }
//     ***********************************************************************
    public void deleteItem(int n){
        items.removeElementAt(n);
        countItems();
    }
//     ***********************************************************************
    public void deleteItem(Object o){
        items.removeElement(o);
        countItems();
    }
//     ***********************************************************************
    public void addItem(GMenuItem i){
        items.addElement(i);
        countItems();
    }
//     ***********************************************************************
    private int countItems(){
        itemCount = items.size();
        return itemCount;
    }
//     ***********************************************************************
    public void down(){
        if (currentIndex<itemCount-1) currentIndex++;
        else currentIndex = 0;
        fireMenuListeners(DOWN);
    }
//     ***********************************************************************
    public void up(){
        if (currentIndex>0) currentIndex--;
        else currentIndex = itemCount-1;
        fireMenuListeners(UP);
    }
//     ***********************************************************************
    public void left(){
//        if (currentIndex>0) currentIndex--;
//        else currentIndex = itemCount;
        fireMenuListeners(LEFT);
    }
//     ***********************************************************************
    public void right(){
        GMenuItem item = (GMenuItem)items.elementAt(currentIndex);
        if (item.hasSub()) item.showSubmenu();
        fireMenuListeners(RIGHT);
    }
//     ***********************************************************************
    public void select(){
        setVisible(false);
        lastRes = getItem(getCurrentIndex());
        fireMenuListeners(SELECT);
    }
//     ***********************************************************************
    public String getTitle() {
        return title;
    }
//     ***********************************************************************
    public void addMenuListener(GMenuListener ml) {
        menuListener.addElement(ml);
    }
//     ***********************************************************************
    public void setTitle(String title) {
        this.title = title;
    }
//     ***********************************************************************
    private void fireMenuListeners(int e){
        for (int i=0; i<menuListener.size(); i++){
            ((GMenuListener)menuListener.elementAt(i)).menuEvent(e);
        }    
    }
//     ***********************************************************************
    public void menuEvent(int e){
        fireMenuListeners(e);
    }
//     ***********************************************************************
    public int getItemsCount(){
        return items.size();
    }
//     ***********************************************************************
    public int getCurrentIndex() {
        return currentIndex;
    }
//     ***********************************************************************
    public void setCurrentIndex(int currentIndex) {
        this.currentIndex = currentIndex;
    }
//     ***********************************************************************
    public GMenuItem getItem(int i) {
        return (GMenuItem)items.elementAt(i);
    }
//     ***********************************************************************
}



MenuItem
Код

package com.canvas.source.visiel.menu;

import javax.microedition.lcdui.Graphics;
import com.canvas.source.util.GRectangle;

public class GMenuItem{
    private String command;
    private GMenu subMenu;
    private String text;
    private GItemInner inner;
    
    private int activeBgColor = 0x00C0C0C0;
    private int activeFgColor = 0x00FFFFFF;
    
    private int passiveBgColor = 0x0050FFA0;
    private int passiveFgColor = 0x00FFFFFF;
    
//     ***********************************************************************
    public GMenuItem(String t, String c){
        text = t;
        command = c;
    }
//     ***********************************************************************
    public GMenuItem(String t){
        text = t;
        command = t;
    }
//     ***********************************************************************
    public void init(){
        subMenu = new GMenu(command);
    }
//     ***********************************************************************
    public boolean hasSub(){
        return subMenu.getItemsCount()>0;
    }
//     ***********************************************************************
    public String getCommand() {
        return command;
    }
//     ***********************************************************************
    public void setCommand(String command) {
        this.command = command;
    }
//     ***********************************************************************
    public void drawSelf(Graphics g, GRectangle r, boolean active){
        int c = g.getColor();
        if (active){
            // do some changes;
        }
        g.setColor(active?activeBgColor:passiveBgColor);
        g.fillRect(r.getX(),r.getY(),r.getWidth(),r.getHeight());

        g.setColor(active?activeFgColor:passiveFgColor);
        g.drawString(getText(), r.getX()+3, r.getY(), 0);
        g.setColor(c);
        //TODO make it drow itself on the menu (this will better!!!) may be;
    }
//     ***********************************************************************
    public int showSubmenu(){
        return 0;
    }
//     ***********************************************************************
    public GItemInner getInner() {
        return inner;
    }
//     ***********************************************************************
    public void setInner(GItemInner inner) {
        this.inner = inner;
    }
//     ***********************************************************************
    public String getText() {
        return text;
    }
//     ***********************************************************************
    public void setText(String text) {
        this.text = text;
    }
//     ***********************************************************************
}


К остальному относитесь как к черному ящику. Да пусть не пугает вас обилие геттеров и сеттеров. 
Хотя, конечно же, было бы лучше создать интерфейс типа GPaintable и реализовывать его и в GMenu и в GMenuItem, но, как я уже сказал, было это давно. Теперь можно было бы и исправить. 

Автор: Samuil 26.7.2006, 13:56
Сейчас откомпилю посмотрю  smile  

Автор: 02077461 26.7.2006, 14:16
Для компиляции, боюсь, тебе придеться многое менять.
Главное -- посмотри на идею. 

Автор: W0LF 26.7.2006, 20:18
Цитата

Прошу не судить строго, это было давно, и подходил сгаряча, без этапа проектирования.

А чего ж тогда сам так строго судишь новичков? 

Автор: Samuil 26.7.2006, 23:07
Да ладно вам ребят, Вы лучше туториал зацените smile  

Автор: 02077461 27.7.2006, 09:08
Сужу не новичков, а подход.
Как можешь видеть, код мой нуждаеться в некоторой доработке, но я показал метод. И если кто нибудь, например Samuil, доведет его до ума, и выложит здесь вычещенный код, буду весьма рад. Подчеркиваю: я не сужу реализацию, я лишь выразил свое мнение о методе. Кто не согласен с ним, пусть выскажет и приведет свой метод, главное не переходить на личности. 

Автор: Samuil 27.7.2006, 11:16
02077461, Это даже хорошо что каждый приводит свой вариант кода, зто большое плюс для начинающих smile  

Автор: 02077461 27.7.2006, 12:00
Еще раз: не вариант кода, а идея варианта решения задачи.
С точки зрения решения одной задачи твой код вполне работоспособен и наверняка удовлетворяет твои потребности.
Но, что бы пользоваться твоим кодом, мне необходимо иметь код, а не класс или библиотеку. Проанализировать его работу, а не прочитать документацию (или просто пользоваться в IDE автоокончанием строк, так как можно понять, что метод addItem(String item) врядли будет обнулять меню или, к примеру, менять его цвет), и модифицировать код, добавляя необходимые пункты. Это не говоря о гибкости метода. А если нам надо загружать пункты меню из конфигурационного XML файла? И, опережая замечания и остроты хочу заявить, что я не критикую, а разьясняю свою точку зрения по данному вопросу.

Samuil, представь, что ты хочешь разведать маневры армии противника (или приятеля). Ты внимательно наблюдаешь и, желая увеличить производительность собственных войск, начинаешь перенимать опыт. Будешь ли ты записывать каждый шаг каждого солдата, теряя из виду общие перемещения войск, всю тактику. Важна тактика. Но!. Конечно же, если твои "солдаты" подчиняясь твоим приказам будут перемещаться по полю непомерно раскидывая ноги, задвая соратников и общим стадом имитируя брачные игры насекомых, то от безукоризненной тактики не будет никакого проку.

Резюмирую: зри не в код. А вообще, куда нравиться, туда и зри.

У тебя, кстати, получилось откомпилировать пример?
 

Автор: javastic 31.7.2006, 14:49
Моё мнение: на определённом этапе развития нужен материал доступный для понимания и освоения.  

Автор: Samuil 1.8.2006, 09:23
javasticW0LF02077461, Спасибо за оценку smile 

Автор: Zamuta 14.8.2006, 16:13
Ребята, посмотрите пжста. У меня при установке j2mepolish-1.2.4 при выборе опции Commercial / None - GPL я ввожу любые 12 символов и продолжаю установку. Дальше он не про что не говорит, но в манифесте записей пока не смотрел, поэтому пока не знаю оставляет он там свои записи или нет.  Так сказать, информация для размышления ......

Автор: olegrolik 11.2.2007, 19:44
Цитата(02077461 @ 26.7.2006,  10:05)
Тема интересная, но реализация, откровенно, слабая.
Меню не гибкое, объект не инкапсулирован. А что делать, если тебе надо в RunTime изменить меню?. 
Понятно, что это простой пример, однако он далеко не лучший. 
P.S. не мешало бы еще узнать о name conversion от разработчиков.

Что значит объект не инкапсулирован? 
Я так понял из дальнейших объяснений, что в хорошем стиле, этот интерфейс следует писать как библиотеку (для лёгкого изменения)? Это и есть инкапсуляция?

Автор: everyone 12.2.2007, 00:37
Цитата

Что значит объект не инкапсулирован? Что значит объект не инкапсулирован? 

Инкапсуляция - это сокрытие методов и переменных объекта. Смысл её в том, чтобы можно было работать с классом не зная его реализации, посредством интерфейса, предоставленного разработчиком. К тому же это плюс к безопастности и устойчивости кода к ошибкам.
Ответ здесь таков, что просто необходимо написать интерфейс, а в качестве единичного класса или библиотеки это будет представлено - совершенно безразлично.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)