ITPub博客

首页 > Linux操作系统 > Linux操作系统 > [转载]创建基于MIDP的应用(上)

[转载]创建基于MIDP的应用(上)

原创 Linux操作系统 作者:dinner1007 时间:2019-01-11 13:09:04 0 删除 编辑
创建基于MIDP的应用(上)
摘要
  这部分主要介绍使用非图形用户接口组件来开发一个应用。此外,还介绍了转换和存储应用数据到MIDlet RecordStore的处理。

  在前面我们主要对配置J2MEWTK环境和MIDP API做了一个简单介绍。本文则通过一个简单的证券事务管理应用,对如何使用非图形用户接口组件进行开发做了介绍。此外,还介绍了转换和存储应用数据到MIDlet RecordStore中。

  Displayable对象的层次

  在前文的例子中,我介绍了两个主要的Displayables类:Canvas和Screen。

  Canvas是Displayable中用来给开发者创建整个用户接口的。对于创建复杂的用户界面非常有用,例如视频游戏中使用的界面。UI在Canvas对象上的绘画与applet中的AWT Canvas类似。

  Screen是Displayable中用来给开发者使用预定义的组件来创建用户界面的。这个组件和那些用来构造Applet的AWT组件类似,例如Label和TextField。如果你选择它来构造你的用户界面,你需要在Abstract Screen对象的子类中加入组件。

  由于Canvas对象在前面的文章中已经详细讨论过了,因此本文中我将主要介绍Displayable中的Screen类。Screen类是Displayable的一个抽象类,Screen类的子类是Alert, Form, List和TextBox。

  在接下来的这篇文章中,我将详细介绍这些Displayable对象,包括它们的构造、交互和事件处理,以便使用它们来构造一个应用。
  详细的例子

  通过例子来学习是一个最好的方法。这个例子主要介绍以下的概念:

   1、使用不同的screen类来构造

   2、使用不同的screen组件来构造

   3、javax.microedition.lcdui类中的命令使用

   4、MVC的实现(用作有效的screen处理)

   5、和存储在设备上的javax.microedition.rms数据交互

  我将采用一个简单的证券应用作线索。在这个应用中,用户可以买卖他拥有的证券。当然,为了介绍主要的概念,这个处理是被大大简化的。

  在本系列的第三部分文章中,我将扩展这个应用来和一个售票服务连接,通过HTTP,得到准确的价格信息。

  ExampleMidlet

  这个应用代码在ExampleMidlet中。它控制流并且可对定义在MIDP规范中的设备资源进行访问。

   public class ExampleMidlet extends MIDlet implements Controller

如上所示,ExampleMidlet通过实现Controller接口来管理屏幕交互。Controller接口的目的是为view和model类提供所需的服务。

  Controller接口

  Controller接口包含有访问StockDatabase的方法,StockDatabase是一个简单的RMS data store,该接口还负责操作MIDlet相关的Display对象。这个例子中的Controller接口是很简单的,你可以扩展它包含的方法,用来得到属性,建立HTTP连接,或者是任何应用中需要用到的其他东西。

public interface Controller
{
 public StockDatabase getStockDatabase();
 public Displayable currentScreen();
 public void nextScreen(Displayable display);
 public void lastScreen();
}

  通过实现Controller接口,ExampleMidlet可以对单个屏幕使用一些方法。你可以将MIDlet作为一个参数传送给Screen,不过你可能不想和普通的MIDlet生命周期打交道。

  在ExampleMidlet中,nextScreen()和lastScreen() 方法用来操作当前可视屏幕的信息。这些方法使用java.util.Stack 对象来操作显示的状态。

  在调用nextSreen来显示下一个屏幕前,这个应用将把当前显示的Displayable对象放入堆栈中。

public void nextScreen(Displayable display){
 Displayable currentScreen = this.getDisplay().getCurrent();

 if ( currentScreen != null)
  _screenStack.push( currentScreen );

  getDisplay().setCurrent( display);
 }

  这个应用将会在堆栈中弹出以前显示的Displayable对象,并且设置显示来展示该屏幕。

public void lastScreen()
{
 Displayable display = null;

 if ( !_screenStack.empty() )
  display = (Displayable) _screenStack.pop();
 else
  display = new WelcomeScreen( (Controller) this );

 getDisplay().setCurrent( display);
}

  你还可以通过其它的方法来处理屏幕的操作。例如,你可以由一个属性文件中读入一个屏幕,并且使用该列表来管理显示屏幕间的交互。不过,这里使用的方法要简单一些。
  WelcomeScreen

  用户首先看到的屏幕是WelcomeScreen。以下我们将谈论一下这个屏幕的代码。WelcomeScreen由javax.microedition.lcdui.List对象扩展而来,并且实现了CommandListener接口。

public class WelcomeScreen extends List implements CommandListener

  该构造器要传送一个包含有Controller的引用作为参数,该参数将存储为一个private变量作以后使用。

public WelcomeScreen(Controller controller)

  由于WelcomeScreen扩展了List对象,因此必须调用超类来作初始化。传送的参数是屏幕的标题和list的类型。

Super("Welcome", List.IMPLICIT);

  List

  在这里使用的list类型是IMPLICIT。你可以使用的list类型如下表所示。

List类型定义
IMPLICIT在一个list中,checkboxes和radio按钮之间都是不可见的。用户只可以在list中选择其中一个项目。与一个HTML项目列表类似。
EXPLICIT Radio按钮只允许用户在list中选择仅有一个项目
MULTIPLECheckboxes允许用户从列表中选择多个项目

  Ticker

  WelcomeScreen还包含有一个Ticker,用来产生一个简单的欢迎信息给用户。要创建一个ticker,调用一个使用String对象的构造器,该字符串包含有滚动的信息,然后可调用Screen对象的setTicker()方法来将该ticker加入到头部。

Ticker ticker =
 new Ticker("Thank you for viewing the Stock Application Example");

this.setTicker( ticker);

  使用append()方法,你可以在列表中加入要显示的项目。

append("Buy Stock", null);
append("Sell Stock", null);

  在显示时,WelcomeScreen将监听和处理所有的命令。因此,它调用一个带this参数的setCommandListener()方法。

this.setCommandListener(this);

  CommandListener

  下面将在WelcomeScreen例子中简要讨论一个MIDlet中的事件处理架构,它可让你处理由MIDlet Screen对象产生的事件。

  事件是由用户的动作产生的,例如在菜单的按钮上点击或者在一个List中选择一个项目。当这些事件产生时,将会执行该对象的CommandAction()方法,这些方法应该在当前屏幕中注册过。

  在WelcomeScreen的例子中,用户可看到一个包含有两个项目的列表:“Buy Stock”和“Select Stock”。然后用户就可以使用上/下箭头来选择其中一个项目,然后按下执行的按钮,这时就会执行commandAction()方法。

public void commandAction (Command c, Displayable d)
{
 if ( c == List.SELECT_COMMAND)
 {
  List shown = (List) _controller.currentScreen();

  switch (shown.getSelectedIndex())
   {
    case 0:
     _controller.nextScreen( new BuyStockScreen( _controller)
      );
     break;
    case 1:
     default:
     _controller.nextScreen( new SelectStockScreen(_controller)
      );
    }
  }
}

  CommandAction()方法解释了如何捕捉一个由IMPLICIT列表产生的事件。第一步是由显示中得到该list,在这个例子中是通过Controller接口完成的。选择的项目可由list中得到,以便根据选择执行相应的逻辑操作。在这个例子中,下一个显示对象将会被初始化,并且传送给Controller的nextScreen()方法。
  BuyStockScreen

  在这个例子中,假设用户已经在Welcome的屏幕中选择了“Buy Stock”的项目。在这个部分中,我将介绍被初始化的BuyStockScreen对象。

public class BuyStockScreen extends StockScreen implements CommandListener

  BuyStockScreen类扩展了StockScreen类,而该类是由javax.microedition.lcdui.Form类扩展而来的。

  StockScreen

  屏幕的标题和一个controller对象的引用将会传送到该构造器中,它们将被存储到一个protected的变量中,以被其子类使用。传送标题的原因是由于StockScreen对象是被BuyStockScreen, SelectStockScreen和SellStockScreen类继承的。

public StockScreen(String title, Controller controller)
{
 super(title);

 _controller = controller;
 _stockDB = controller.getStockDatabase();
}

  在构造器中,一个令人感兴趣的项目是:StockScreen类接收一个到StockDatabase接口的引用,以便给子类使用。

public void displayScreen(String symbol, int numShares)
{
 _symbolField = new StringItem("Stock Symbol: ", symbol);
 _numSharesField = new StringItem("Num Shares: ", ""+ numShares);

 append(_symbolField);
 append(_numSharesField);

 generateButtons();
}

public void displayScreen()
{
 _symbolEntry = new TextField("Enter Stock Symbol", "", 6,  
                TextField.ANY);
 _numEntry = new TextField("Enter Num Shares", "", 10,  
              TextField.NUMERIC);
 
 append(_symbolEntry);
 append(_numEntry);

 generateButtons();
}

  有两种的displayScreen()方法来解释两种不同的用户接口组件:StringItem 和 TextField。

  StringItem

  StringItem是一个仅用来显示的项目,它包含有一个标签和一个相应的值。在这个例子中,StringItem是用来显示卖单的股票及其数目。

  TextField

  TextField是一个UI组件,可让用户通过电话上的键盘来为应用输入信息。TextField接收以下的参数:

  Label(标签)

  Initial text (初始化的文本)

  Maximum length (最大长度)

  Field constraint (字段限制)

下面的表格说明了可以使用的字段限制

字段限制描述
ANY用户可输入任意的文本
EMAILADDR用户可输入一个email地址
NUMERIC用户只可以输入一个整型值
PASSWORD 输入的字符不可见
PHONENUMBER 用户可输入一个电话号码
URL用户可输入一个URL

  要注意的是,不同的MIDP规范是有一些区别的。例如,电话号码字段可包含额外的字符,例如+号在欧洲的电话号码中是广泛使用的。在规范变得更为标准化前,你需要在应用中注意到这些细节。

  两种DisplayScreen()方法将调用generateButtons()方法来创建“Next”和“返回”按钮,这些按钮都将在所有三个子类屏幕上使用。在这个方法中,每一个Command对象都被初始化,并且通过addCommand()方法加入到屏幕上。

public void generateButtons()
{
 this.nextCommand = new Command("Next", Command.SCREEN, 1);
 this.backCommand = new Command("Back", Command.BACK, 1);

 this.addCommand(backCommand);
 this.addCommand(nextCommand);
}
}
  再次讨论BuyStockScreen

  回到BuyStockScreen,由于超类已经处理了所有的初始化,因此这个屏幕仅需要设置它的CommandListener动作。

public BuyStockScreen(Controller controller)
{
 super("Buy Stock", controller);

 super.displayScreen();

 this.setCommandListener(this);
}

  在CcommandAction()方法中,第一个的检查是看用户是否点击了“Back”按钮。如果是的话,将会调用 Controller来显示上一个屏幕(由堆栈中得到)。

public void commandAction(Command c, Displayable d)
{
 if ( c == backCommand)
 {
  _controller.lastScreen();
 }


  如果用户点击的是“Next”按钮,就会开始购买股票的处理。在这个处理中,必须得到TextField的参数。StockDatabase的接口将会调用buyStock()方法,将新购买的股票加入到股票数据库中。如果处理没有出错,WelcomeScreen将会再一次显示。

else
{
// buy the shares
try
{
String symbol = _symbolEntry.getString();
String shares = _numEntry.getString();

_stockDB.buyStock( symbol, shares, 4);

_controller.nextScreen( new WelcomeScreen( _controller) );
}
catch (StockException se)
{
this.setTitle("Bad Data");

se.printStackTrace();
}
}
  StockDatabase

  StockDatabase接口是为了将MIDP存储实现的功能由应用中抽象出来。由于UI开发者无需知道数据存储的技术细节,因此将这个级别抽象出来是非常有用的。

public interface StockDatabase
{
 public void buyStock(String symbol, String shares, int price)
               throws StockException;
 public void sellStock(Stock stock, int numShares) throws
                StockException;
 public Vector getStocks() throws StockException;
 public Stock getStock(String stock) throws StockException;
}

  StockDatabase接口包含有由MIDlet RecordStore中加入、接收和移除数据的方法。StockDatabase和相应数据存储的细节将会在讨论UI组件时再介绍。

  SelectStockScreen

  SelectStockScreen屏幕显示个人股票的列表,这些数据是由数据库中得到的。这个对象的构造器负责初始化显示。在StockScreen的讨论中已经提到,在这个超类的构造器中已经得到了StockDatabase的引用,也就是_stockDB。getStocks()方法用来得到个人股票的一个列表。如果找到相关的数据,包含有这些股票的一个Vector将会返回并且传送给showStockList()方法,以便转换为一个友好的用户界面。

public SelectStockScreen(Controller controller)
{
 super("Select Stock", controller);

 try
 {
  Vector stocks = _stockDB.getStocks();

  Item displayItem = showStockList(stocks);

  append(displayItem);

  super.generateButtons();

  this.setCommandListener( this);
 }
 catch (StockException se)
 {
  append(se.getMessage() );
 }
}

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-131815/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-08-23

  • 博文量
    1006
  • 访问量
    727591