工作两差吾多两个月了, 里段时间里我都在做一个j2me项目, 项目是用到polish进行UI开发。回想起刚开始对polish的认识, 我系里度谈谈对polish噶认识。
J2ME Polish是德国人的一个开源项目,主页是:http://www.j2mepolish.org/,类似于一个java开发环境的插件。本人开发环境是:window下netbeans 5+jdk1.5+Mobility +polish 2.0 RC4。安装polish很简单,从主页下载落来双击就可以安装了,如果你的机不能运行jar文件,则可以在cmd中用 “java -jar j2mepolish-2.0.jar ”就可以运行了(前提是你安装着jdk,且环境变量设置正确)。
安装过程中,选择wtk.home和选择安装在netbeans和全部api,其他默认就可以了。安装后重启netbeans 就会自动嵌入netbeans中的了。下面我们来创建一个polish项目:
有两种方法,一是在netbeans中创建polish项目(polish自带的samples),但这要清楚samples对应要用到的api 和支持的devices(相应你要装有此device),所以本人一般不用此方法。二是创建普通的Mobile application,然后把polish里边sample里的build.xml文件copy到工程目录下,修改<midlet /> 属性值,同时引入相应的api 包(/lib/enough-j2mepolish-build.jar 和 /lib/jdom.jar 一定要引入) 就行了。
上次介绍了一下 polish的大概。其实本人我对j2me和polish都是刚接触的,以下来我会同时介绍j2me和polish的学习心得。以下我们以一个 expenses tracker(builder.com里的一个例子)的例子来介绍建立polish项目(这个例子可以在)。
在netbeans我们可以先建立一个一般的Mobile的项目,按netbeans 向导很容易建立。这里工程expenses tracker里有两个类:
Expenses.java:
/*
Expenses
A sample J2ME MIDP application that illustrates the use
of List and Command UI components
Copyright 2002 CNet Networks
*/
package ExpensesApp;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.Vector;
public class Expenses extends MIDlet implements CommandListener {
private Display display;
private Vector expenseItems;
private List lsMain;
private Command cmAdd, cmEdit, cmExit, cmMenu;
private int itemCount = 0;
public Expenses() {
display = Display.getDisplay(this);
// get some play data
expenseItems = ExpenseInfo.LoadExpenses();
itemCount = expenseItems.size();
// Setup the UI
lsMain = new List("Expenses", List.IMPLICIT) ;
cmAdd = new Command("New", Command.SCREEN, 3);
cmEdit = new Command("Edit", Command.ITEM, 2);
cmExit = new Command("Exit", Command.EXIT, 1);
lsMain.addCommand(cmAdd);
lsMain.addCommand(cmEdit);
lsMain.addCommand(cmExit);
lsMain.setCommandListener(this);
// add all the Expense items to lsMain
rebuildList();
}
public void startApp() throws MIDletStateChangeException {
// Show the main UI form
display.setCurrent(lsMain);
}
public void commandAction(Command cm, Displayable d) {
if (cm == List.SELECT_COMMAND || cm == cmEdit) {
// User selected an item in lsMain or
// invoked the "Edit" command from the menu
// Edit an item, we'll implement this later
} else if (cm == cmAdd) {
// User invoked the "Add" command from the menu
// Add a new item, we'll implement this later
} else if (cm == cmExit) {
// User invoked the "Exit" command
destroyApp(false);
notifyDestroyed();
}
}
public void pauseApp() {
}
public void destroyApp(boolean b) {
}
private void rebuildList(){
// add all the expense items to lsMain
for(int i=0; i<expenseItems.size(); i++){
if (expenseItems.elementAt(i) != null){
ExpenseInfo exp = (ExpenseInfo) expenseItems.elementAt(i);
lsMain.append(exp.getDescription(),null);
}
}
}
}
ExpenseInfo.java:
/*
ExpenseInfo
Models an expense item for the sample Expenses
J2ME MIDP application
Copyright 2002 CNet Networks
*/
package ExpensesApp;
import java.util.Date;
import java.util.Vector;
public class ExpenseInfo {
// Expense Item categories
public static final String[] Categories = {"Meals","Lodging","Car","Entertain","Misc"};
public static final int CATEGORY_MEALS = 0, CATEGORY_LODGING = 1,
CATEGORY_CAR = 2, CATEGORY_ENTER = 3, CATEGORY_MISC = 4;
// member variables
private Date ExpenseDate;
private String ExpenseDescription;
// We don't have floating point support,
// so we have to fake it with two int variables
// to store the amount of the expense
private int ExpenseDollars;
private int ExpenseCents;
private int ExpenseId;
private String ExpenseCategory;
private int ExpenseCategoryID;
public static Vector LoadExpenses() {
// Eventually, we'll need to load expenses from
// the data store into this vector, but for now
// let's just load some play data
Vector v = new Vector();
ExpenseInfo exp = new ExpenseInfo();
exp.setDescription("Car Rental");
exp.setDollars(25);
exp.setCents(99);
exp.setCategoryID(CATEGORY_CAR);
v.addElement(exp);
exp = new ExpenseInfo();
exp.setDescription("Hotel");
exp.setDollars(54);
exp.setCents(00);
exp.setCategoryID(ExpenseInfo.CATEGORY_LODGING);
v.addElement(exp);
exp = new ExpenseInfo();
exp.setDescription("Dinner");
exp.setDollars(18);
exp.setCents(78);
exp.setCategoryID(ExpenseInfo.CATEGORY_MEALS);
v.addElement(exp);
return v;
}
public ExpenseInfo(){
ExpenseDate = new Date();
ExpenseDescription = "";
ExpenseDollars = 0;
ExpenseCents = 0;
ExpenseCategoryID = ExpenseInfo.CATEGORY_MISC;
}
public void save() {
// mock saving data by printing to the console
System.out.println (ExpenseDate.toString() + " " + ExpenseDescription
+ " $" + String.valueOf(ExpenseDollars) + "." + String.valueOf(ExpenseCents));
}
// The rest of these are simply accessor methods
// for the class's private fields.
public void setDate(Date newDate){
ExpenseDate = newDate;
}
public Date getDate(){
return ExpenseDate;
}
public void setDescription(String newDescription){
ExpenseDescription = newDescription;
}
public String getDescription(){
return ExpenseDescription;
}
public void setDollars(int newDollars){
ExpenseDollars = newDollars;
}
public int getDollars(){
return ExpenseDollars;
}
public void setCents(int newCents){
ExpenseCents = newCents;
}
public int getCents() {
return ExpenseCents;
}
public String getCategory(){
return ExpenseCategory;
}
public int getCategoryID(){
return ExpenseCategoryID;
}
public void setCategoryID(int newID){
ExpenseCategoryID = newID;
ExpenseCategory = Categories[newID];
}
}
运行此工程如下:
现在我们来让这个工程变为polish工程:
我们可以把{polish.home}/sample/blank里的blank例子里的全部文件copy到expenses tracker 工程下,然后把原来expenses tracker工程文件夹下的src文件夹移入source文件夹里。把build-netbeans.xml改名为build.xml替换旧的 build.xml文件。
然后我们来修改build.xml: 1)、工程名可以可以改为
ExpensesTracker, <j2mepolish></j2mepolish>中的<info> jarName可改为: jarName="${polish.vendor}-${polish.name}-${polish.locale}-ExpensesTracker.jar" (这是生成的jar和jad的名称,你也可以不改)。
2)、把全部<deviceRequirements> 注释掉改为:
<deviceRequirements>
<requirement name="Identifier" value="Generic/midp1" />
</deviceRequirements>
这里你可以把value值改为你想显示的模拟器,但是模拟器要安装在你机上,且polish支持(可以查看{polish.home}里的devices.xml文件看polish是否支持)。
3)、<midlet />属性改为你工程的midlet类本例子如下:
<midlet class="ExpensesApp.ExpenseInfo" name="ExpenseInfo" />
4)、引入{polish.home}/import/enough-j2mepolish-client.jar;
(注:我们也可以不用建立工程,直接把blank工程copy到你的工程目录下, 然后把你的旧工程代码src目录放入cource文件夹, 然后按上边的修改后在netbeans打开工程就可以了。)
现在就可以运行程序看看效果:
现在我们来说说上边的ExpensesTracker里边用到的j2me知识,同时我会介绍polish,通过polish来美化 ExpensesTracker。我会从j2me基本的GUI(主要是javax.microedition.lcdui;类)编程,然后会讨论j2me 里的数据存储。
ExpensesTracker 程序里边由一个单独的MIDlet(Expenses)和一个数据类(ExpenseInfo)组成。Expenses提供了简单的UI,而 ExpenseInfo则定义了数据的结构(fields for data and time, description, amount, and category )。因为lcdc1.0是不支持floating-point数据的(lcdc1.1支持),所在在ExpenseInfo里用两个独立的int 来记录expense amount的dollars和cents。
基本UI:
从上边工程运行的效果来看,Expenses UI 由一个List 组件(显示了你记录了的Expense条目)和三个Command 组件(quitting the app, editing an item, adding a new item)组成。
List是继承Screen类而来的,在j2me中的List组件其有三种类型:
· Implicit Lists (Expenses里是用此类型) :允许只能选择一个item, 当你选择某个item时会触发commandAction 事件。
· Exclusive Lists(单选):以radio按钮形式显示,一次只能选择一个item,选择时不会触发commandAction 事件。
· Multiple Lists(多选): 以check boxes 按钮形式显示,允许多选,选择时不会触发commandAction事件。
当用户选择之后,可以通过下面的方法返回选定的索引值:
getSelectedIndex()--------返回List中一个选定项的索引值。
Polish工程项目的编译,运行,打包等等,是由build.xml文件控制的。下边是ExpensesTracker工程里的build.xml:
<project
name="ExpenseTracker"
default="j2mepolish">
<!-- extend the default NetBeans build script: -->
<import file="nbproject/build-impl.xml"/>
<!-- import user specific properties -->
<property file="${user.name}.properties" />
<!-- The polish.home property needs to point to the directory -->
<!-- containing the J2ME Polish installation. -->
<property name="polish.home" location="C:\Program Files\J2ME-Polish" />
<!-- import global properties -->
<property file="${polish.home}/global.properties" />
<!-- Definition of the J2ME Polish task: -->
<taskdef name="j2mepolish"
classname="de.enough.polish.ant.PolishTask"
classpath="${polish.home}/lib/enough-j2mepolish-build.jar:${polish.home}/lib/jdom.jar"
/>
<!-- build targets, each target can be called via "ant [name]",
e.g. "ant clean", "ant test j2mepolish" or just "ant" for calling the default-target -->
<target name="j2mepolish-init"
depends="init"
>
<property name="test" value="false" />
<property name="customization" value="" />
<property name="dir.work" value="build/real/${customization}" />
<property name="dir.dist" value="dist/${customization}" />
<property name="deploy-url" value="" />
</target>
<!-- In this target the J2ME Polish task is used. -->
<!-- It has 3 sections: -->
<!-- 1. The info-section defines some general information -->
<!-- 2. The deviceRequirements-section chooses the devices -->
<!-- for which the application is optimized. -->
<!-- 3. The build-section controls the actual build -->
<!-- process. -->
<target name="j2mepolish"
depends="j2mepolish-init"
description="This is the controller for the J2ME build process."
>
<j2mepolish>
<!-- general settings -->
<info copyright="Copyright 2006, 2007 Your Company. All rights reserved."
description="Please describe me."
infoUrl="http://www.j2mepolish.org"
jarName="${polish.vendor}-${polish.name}-${polish.locale}-ExpenseTracker.jar"
jarUrl="${deploy-url}${polish.jarName}"
name="ExpenseTracker"
vendorName="Enough Software"
version="1.0.0"
/>
<!-- selection of supported devices -->
<deviceRequirements if="config.active:defined and (test or enableCompilerMode)" >
<requirement name="Identifier" value="${config.active}" />
</deviceRequirements>
<deviceRequirements if="device:defined and (test or enableCompilerMode)" unless="config.active:defined">
<requirement name="Identifier" value="${device}" />
</deviceRequirements>
<deviceRequirements unless="test or enableCompilerMode">
<requirement name="Identifier" value="${devices}" />
</deviceRequirements>
<!-- build settings -->
<build fullscreen="menu"
symbols="polish.skipArgumentCheck"
usePolishGui="true"
workDir="${dir.work}"
destDir="${dir.dist}"
>
<!-- midlets definition -->
<!-- NetBeans defines this property automatically: -->
<midlets definition="${manifest.midlets}" if="manifest.midlets:defined" />
<midlets unless="manifest.midlets:defined">
<midlet class="ExpensesApp.Expenses" name="ExpensesTracker" />
</midlets>
<!-- project-wide variables - used for preprocessing -->
<variables>
<!-- Sample configuration options for J2ME Polish
<variable name="polish.TextField.useDirectInput" value="true" />
<variable name="polish.TextField.supportSymbolsEntry" value="true" />
<variable name="polish.MenuBar.useExtendedMenuBar" value="true" />
<variable name="polish.useScrollBar" value="true" />
-->
</variables>
<!-- Configure the customization settings here: -->
<resources
dir="resources/base"
defaultexcludes="yes"
excludes="readme.txt"
>
<root dir="resources/base/images" />
<root dir="resources/base/sounds" />
<root dir="resources/${customization}" if="build.${customization}" />
<root dir="resources/${customization}/images" if="build.${customization}" />
<root dir="resources/${customization}/sounds" if="build.${customization}" />
<!-- add the localization element for created localized
versions of your application:
<localization>
<locale name="en_US" />
<locale name="de_DE" encoding="utf-8" unless="test" />
</localization>
-->
</resources>
<!-- obfuscator settings: do not obfuscate when the test-property is true -->
<obfuscator name="ProGuard" unless="test" >
<!--
You can set additional parameters here, e.g.:
<parameter name="optimize" value="false" />
-->
</obfuscator>
<!-- log settings: only use debug setting when the test-property is true -->
<debug if="test" showLogOnError="true" verbose="true" level="error">
<filter pattern="de.enough.polish.example.*" level="debug" />
<filter pattern="de.enough.polish.ui.*" level="warn" />
<!-- example for writing log entries to the Recordstore Management System:
<handler name="rms" />
-->
</debug>
<!-- user defined JAD attributes can also be used: -->
<jad>
<attribute name="Nokia-MIDlet-Category" value="Game" if="polish.group.Series40" />
</jad>
</build>
<!-- execution of emulator(s) -->
<emulator
wait="true"
trace="none"
securityDomain="trusted"
enableProfiler="false"
enableMemoryMonitor="false"
enableNetworkMonitor="false"
if="test and not debug"
>
<!--
<parameter name="-Xjam" value="transient=http://localhost:8080/${polish.jadName}" />
-->
</emulator>
<emulator
wait="true"
securityDomain="trusted"
enableProfiler="false"
enableMemoryMonitor="false"
enableNetworkMonitor="false"
if="debug"
>
<!-- Attach the emulator to the NetBeans debugger: -->
<debugger name="antcall" target="connect-debugger" port="6001" />
</emulator>
</j2mepolish>
</target>
<target name="setdeploy"
description="Call this target first to set the OTA download-URL, e.g. ant setdeploy j2mepolish"
>
<property name="deploy-url" value="http://www.company.com/download/" />
</target>
<target name="enableDebug"
description="Call this target first to skip the obfuscation step, call the emulator and start the debugger, e.g. ant enableDebug j2mepolish"
>
<property name="debug" value="true" />
</target>
<target name="enableEmulator"
description="Call this target first to skip the obfuscation step and call the emulator, e.g. ant test j2mepolish"
>
<property name="test" value="true" />
<property name="dir.work" value="build/test" />
</target>
<target
name="emulator"
depends="enableEmulator,j2mepolish"
description="invokes the emulator"
>
</target>
<target name="clean"
description="allows a clean build. You should call [ant clean] whenever you made changes to devices.xml, vendors.xml or groups.xml">
<delete dir="build" />
<delete dir="dist" includes="**/*" />
</target>
<target
name="cleanbuild"
description="allows a clean build. You should call [ant cleanbuild] whenever you made changes to devices.xml, vendors.xml or groups.xml"
depends="clean, j2mepolish"
/>
<target name="debug" description="debugs the project" depends="enableDebug, enableEmulator, j2mepolish" />
<target name="deploy"
description="Deploys the applications. Currently empty."
depends="j2mepolish"
/>
<!-- NetBeans specific build targets: -->
<target name="run"
depends="enableEmulator, j2mepolish"
>
</target>
<target name="rebuild"
depends="clean, j2mepolish"
>
</target>
<target name="rebuild-all"
depends="clean, j2mepolish"
>
</target>
<target name="jar"
depends="j2mepolish"
>
</target>
<target name="jar-all"
depends="j2mepolish"
>
</target>
<target name="clean-all"
depends="clean"
>
</target>
<target name="deploy-all"
depends="deploy"
>
</target>
<target name="enable-compiler-mode">
<property name="enableCompilerMode" value="true" />
</target>
<target name="compile-single"
depends="enable-compiler-mode, j2mepolish"
>
</target>
<target name="connect-debugger">
<property name="jpda.port" value="${polish.debug.port}" />
<antcall target="nbdebug"/>
</target>
<target name="enableCustomization1">
<property name="dir.work" value="build/customization1" />
<property name="cfg.customization1" value="true" />
</target>
<target name="customization1"
description="customizes this project with the settings found in resources/customization1"
depends="enableCustomization1, j2mepolish"
/>
<target name="enableCustomization2">
<property name="dir.work" value="build/customization2" />
<property name="cfg.customization2" value="true" />
</target>
<target name="customization2"
description="customizes this project with the settings found in resources/customization2"
depends="enableCustomization2, j2mepolish"
/>
</project>
build.xml文件中最主要的是<info>,<deviceRequirements>和<build>三部分。
其中<info>元素指定说明了工程中的一般信息,如,工程名和版本。<deviceRequirements> 元素是用来指定程序编译时所选择的模拟器。<build>元素是工程编译构件时的主要控制器(如,可以设定属性 usePolishGui=”true”来指定把polish应用当前工程中,而设为false时,则说明当前工程不引入polish,此时工程与一般的 mobile应用程序一样)。
当build.xml文件中的<build>属性usePolishGui=”true”时,我们就可以修改工程目录中 resources里的polish.css文件控制程序的显示(美化j2me介面)。在j2me程序中只需要以“//#style”指令就可以调用相应的css属性(请注意这指令与注释“//”的区别)。其中,polish.css文件包含对应用程序的全部items和screens的style定义。
polish.css文件中常用的预定义的style(用于程序中的所有items和screens,但当引用自定义style时,预定义的style会被自定义style覆盖掉:
colors{}:用来定义一系列的颜色,供其它style中的color属性引用。
backgrounds{}:用来定义一系列的背景,供其它style中的background属性引用。
borders{}:用来定义一系列的边框,供其它style中的border属性引用。
focused{}:当获取某个item或screen的焦点时的style。
title{}:应用于所以screen中的title的style。
scrollbar{}:当build.xml文件中“polish.useScrollBar“变量设为true时被scrollbar引用。
label{}:应用于所以item或menu中标签的style。
以下style是当build.xml文件中“polish.MenuBar.useExtendMenuBar“变量设为true时被引用的:
menubar{}, menu{},menuItem{},leftcommand{},rightcommand{}
polish.css文件中自定义style:
注意:styel可以继承的,且引用子style时既保留父style的属性又有自己的属性,同时子style可以重写父style属性。
自定义style名称:如“.mystyle{}”是由点加字符串。注意不能是与预定义的名称相同。
下面我们来对ExpensesTracker中的UI---List以CSS进行修改。
修改后程序运行如下:
其polish.css文件:
colors {
fontColor: rgb( 30, 85, 86 );
focusedFontColor: #000;
bgColor: #eee;
focusedBgColor: #fff;
borderColor: fontColor;
focusedBorderColor: focusedFontColor;
}
focused {
margin: 1;
margin: 3;
background {
type: round-rect;
arc: 4;
color: focusedBgColor;
border-color: focusedBorderColor;
border-width: 2;
}
font {
style: bold;
color: focusedFontColor;
size: small;
}
layout: expand;
}
/**
* The title style is a predefined style which is used
* for all screen-titles.
*/
title {
padding: 2;
font-face: proportional;
font-size: large;
font-style: bold;
font-color: focusedFontColor;
border: none;
background {
type: vertical-gradient;
top-color: #fff;
bottom-color: rgb(140,206,220);
start: 10%;
end: 90%;
}
layout: expand|center;
}
.expenseList{
background {
image:url(BG.png);
color: rgb(184,235,246)
}
}
.expenseItem{
margin: 3;
padding-left: 3;
font-face: proportional;
font-size: small;
font-style: bold;
font-color: focusedFontColor;
focused-style: expenseItemFocused;
}
.expenseItemFocused extends .expenseItem{
background-color: argb( 150, 255, 255, 255 );
after: url(listItem.png);
layout:expand;
}
而Expenses.java中引用CSS的地方(绿色字体):
public Expenses() {
display = Display.getDisplay(this);
//get some play data
expenseItems = ExpenseInfo.LoadExpenses();
itemCount = expenseItems.size();
//Setup the UI
//#style expenseList
lsMain = new List("Expenses", List.IMPLICIT) ;
cmAdd = new Command("New", Command.SCREEN, 3);
cmEdit = new Command("Edit", Command.ITEM, 2);
cmExit = new Command("Exit", Command.EXIT, 1);
lsMain.addCommand(cmAdd);
lsMain.addCommand(cmEdit);
lsMain.addCommand(cmExit);
lsMain.setCommandListener(this);
//add all the Expense items to lsMain
rebuildList();
}
private void rebuildList(){
//add all the expense items to lsMain
for(int i=0; i<expenseItems.size(); i++){
if (expenseItems.elementAt(i) != null){
ExpenseInfo exp = (ExpenseInfo) expenseItems.elementAt(i);
//#style expenseItem
lsMain.append(exp.getDescription(),null);
}
}
}
J2ME Polish是德国人的一个开源项目,主页是:http://www.j2mepolish.org/,类似于一个java开发环境的插件。本人开发环境是:window下netbeans 5+jdk1.5+Mobility +polish 2.0 RC4。安装polish很简单,从主页下载落来双击就可以安装了,如果你的机不能运行jar文件,则可以在cmd中用 “java -jar j2mepolish-2.0.jar ”就可以运行了(前提是你安装着jdk,且环境变量设置正确)。
安装过程中,选择wtk.home和选择安装在netbeans和全部api,其他默认就可以了。安装后重启netbeans 就会自动嵌入netbeans中的了。下面我们来创建一个polish项目:
有两种方法,一是在netbeans中创建polish项目(polish自带的samples),但这要清楚samples对应要用到的api 和支持的devices(相应你要装有此device),所以本人一般不用此方法。二是创建普通的Mobile application,然后把polish里边sample里的build.xml文件copy到工程目录下,修改<midlet /> 属性值,同时引入相应的api 包(/lib/enough-j2mepolish-build.jar 和 /lib/jdom.jar 一定要引入) 就行了。
上次介绍了一下 polish的大概。其实本人我对j2me和polish都是刚接触的,以下来我会同时介绍j2me和polish的学习心得。以下我们以一个 expenses tracker(builder.com里的一个例子)的例子来介绍建立polish项目(这个例子可以在)。
在netbeans我们可以先建立一个一般的Mobile的项目,按netbeans 向导很容易建立。这里工程expenses tracker里有两个类:
Expenses.java:
/*
Expenses
A sample J2ME MIDP application that illustrates the use
of List and Command UI components
Copyright 2002 CNet Networks
*/
package ExpensesApp;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.Vector;
public class Expenses extends MIDlet implements CommandListener {
private Display display;
private Vector expenseItems;
private List lsMain;
private Command cmAdd, cmEdit, cmExit, cmMenu;
private int itemCount = 0;
public Expenses() {
display = Display.getDisplay(this);
// get some play data
expenseItems = ExpenseInfo.LoadExpenses();
itemCount = expenseItems.size();
// Setup the UI
lsMain = new List("Expenses", List.IMPLICIT) ;
cmAdd = new Command("New", Command.SCREEN, 3);
cmEdit = new Command("Edit", Command.ITEM, 2);
cmExit = new Command("Exit", Command.EXIT, 1);
lsMain.addCommand(cmAdd);
lsMain.addCommand(cmEdit);
lsMain.addCommand(cmExit);
lsMain.setCommandListener(this);
// add all the Expense items to lsMain
rebuildList();
}
public void startApp() throws MIDletStateChangeException {
// Show the main UI form
display.setCurrent(lsMain);
}
public void commandAction(Command cm, Displayable d) {
if (cm == List.SELECT_COMMAND || cm == cmEdit) {
// User selected an item in lsMain or
// invoked the "Edit" command from the menu
// Edit an item, we'll implement this later
} else if (cm == cmAdd) {
// User invoked the "Add" command from the menu
// Add a new item, we'll implement this later
} else if (cm == cmExit) {
// User invoked the "Exit" command
destroyApp(false);
notifyDestroyed();
}
}
public void pauseApp() {
}
public void destroyApp(boolean b) {
}
private void rebuildList(){
// add all the expense items to lsMain
for(int i=0; i<expenseItems.size(); i++){
if (expenseItems.elementAt(i) != null){
ExpenseInfo exp = (ExpenseInfo) expenseItems.elementAt(i);
lsMain.append(exp.getDescription(),null);
}
}
}
}
ExpenseInfo.java:
/*
ExpenseInfo
Models an expense item for the sample Expenses
J2ME MIDP application
Copyright 2002 CNet Networks
*/
package ExpensesApp;
import java.util.Date;
import java.util.Vector;
public class ExpenseInfo {
// Expense Item categories
public static final String[] Categories = {"Meals","Lodging","Car","Entertain","Misc"};
public static final int CATEGORY_MEALS = 0, CATEGORY_LODGING = 1,
CATEGORY_CAR = 2, CATEGORY_ENTER = 3, CATEGORY_MISC = 4;
// member variables
private Date ExpenseDate;
private String ExpenseDescription;
// We don't have floating point support,
// so we have to fake it with two int variables
// to store the amount of the expense
private int ExpenseDollars;
private int ExpenseCents;
private int ExpenseId;
private String ExpenseCategory;
private int ExpenseCategoryID;
public static Vector LoadExpenses() {
// Eventually, we'll need to load expenses from
// the data store into this vector, but for now
// let's just load some play data
Vector v = new Vector();
ExpenseInfo exp = new ExpenseInfo();
exp.setDescription("Car Rental");
exp.setDollars(25);
exp.setCents(99);
exp.setCategoryID(CATEGORY_CAR);
v.addElement(exp);
exp = new ExpenseInfo();
exp.setDescription("Hotel");
exp.setDollars(54);
exp.setCents(00);
exp.setCategoryID(ExpenseInfo.CATEGORY_LODGING);
v.addElement(exp);
exp = new ExpenseInfo();
exp.setDescription("Dinner");
exp.setDollars(18);
exp.setCents(78);
exp.setCategoryID(ExpenseInfo.CATEGORY_MEALS);
v.addElement(exp);
return v;
}
public ExpenseInfo(){
ExpenseDate = new Date();
ExpenseDescription = "";
ExpenseDollars = 0;
ExpenseCents = 0;
ExpenseCategoryID = ExpenseInfo.CATEGORY_MISC;
}
public void save() {
// mock saving data by printing to the console
System.out.println (ExpenseDate.toString() + " " + ExpenseDescription
+ " $" + String.valueOf(ExpenseDollars) + "." + String.valueOf(ExpenseCents));
}
// The rest of these are simply accessor methods
// for the class's private fields.
public void setDate(Date newDate){
ExpenseDate = newDate;
}
public Date getDate(){
return ExpenseDate;
}
public void setDescription(String newDescription){
ExpenseDescription = newDescription;
}
public String getDescription(){
return ExpenseDescription;
}
public void setDollars(int newDollars){
ExpenseDollars = newDollars;
}
public int getDollars(){
return ExpenseDollars;
}
public void setCents(int newCents){
ExpenseCents = newCents;
}
public int getCents() {
return ExpenseCents;
}
public String getCategory(){
return ExpenseCategory;
}
public int getCategoryID(){
return ExpenseCategoryID;
}
public void setCategoryID(int newID){
ExpenseCategoryID = newID;
ExpenseCategory = Categories[newID];
}
}
运行此工程如下:
现在我们来让这个工程变为polish工程:
我们可以把{polish.home}/sample/blank里的blank例子里的全部文件copy到expenses tracker 工程下,然后把原来expenses tracker工程文件夹下的src文件夹移入source文件夹里。把build-netbeans.xml改名为build.xml替换旧的 build.xml文件。
然后我们来修改build.xml: 1)、工程名可以可以改为
ExpensesTracker, <j2mepolish></j2mepolish>中的<info> jarName可改为: jarName="${polish.vendor}-${polish.name}-${polish.locale}-ExpensesTracker.jar" (这是生成的jar和jad的名称,你也可以不改)。
2)、把全部<deviceRequirements> 注释掉改为:
<deviceRequirements>
<requirement name="Identifier" value="Generic/midp1" />
</deviceRequirements>
这里你可以把value值改为你想显示的模拟器,但是模拟器要安装在你机上,且polish支持(可以查看{polish.home}里的devices.xml文件看polish是否支持)。
3)、<midlet />属性改为你工程的midlet类本例子如下:
<midlet class="ExpensesApp.ExpenseInfo" name="ExpenseInfo" />
4)、引入{polish.home}/import/enough-j2mepolish-client.jar;
(注:我们也可以不用建立工程,直接把blank工程copy到你的工程目录下, 然后把你的旧工程代码src目录放入cource文件夹, 然后按上边的修改后在netbeans打开工程就可以了。)
现在就可以运行程序看看效果:
现在我们来说说上边的ExpensesTracker里边用到的j2me知识,同时我会介绍polish,通过polish来美化 ExpensesTracker。我会从j2me基本的GUI(主要是javax.microedition.lcdui;类)编程,然后会讨论j2me 里的数据存储。
ExpensesTracker 程序里边由一个单独的MIDlet(Expenses)和一个数据类(ExpenseInfo)组成。Expenses提供了简单的UI,而 ExpenseInfo则定义了数据的结构(fields for data and time, description, amount, and category )。因为lcdc1.0是不支持floating-point数据的(lcdc1.1支持),所在在ExpenseInfo里用两个独立的int 来记录expense amount的dollars和cents。
基本UI:
从上边工程运行的效果来看,Expenses UI 由一个List 组件(显示了你记录了的Expense条目)和三个Command 组件(quitting the app, editing an item, adding a new item)组成。
List是继承Screen类而来的,在j2me中的List组件其有三种类型:
· Implicit Lists (Expenses里是用此类型) :允许只能选择一个item, 当你选择某个item时会触发commandAction 事件。
· Exclusive Lists(单选):以radio按钮形式显示,一次只能选择一个item,选择时不会触发commandAction 事件。
· Multiple Lists(多选): 以check boxes 按钮形式显示,允许多选,选择时不会触发commandAction事件。
当用户选择之后,可以通过下面的方法返回选定的索引值:
getSelectedIndex()--------返回List中一个选定项的索引值。
Polish工程项目的编译,运行,打包等等,是由build.xml文件控制的。下边是ExpensesTracker工程里的build.xml:
<project
name="ExpenseTracker"
default="j2mepolish">
<!-- extend the default NetBeans build script: -->
<import file="nbproject/build-impl.xml"/>
<!-- import user specific properties -->
<property file="${user.name}.properties" />
<!-- The polish.home property needs to point to the directory -->
<!-- containing the J2ME Polish installation. -->
<property name="polish.home" location="C:\Program Files\J2ME-Polish" />
<!-- import global properties -->
<property file="${polish.home}/global.properties" />
<!-- Definition of the J2ME Polish task: -->
<taskdef name="j2mepolish"
classname="de.enough.polish.ant.PolishTask"
classpath="${polish.home}/lib/enough-j2mepolish-build.jar:${polish.home}/lib/jdom.jar"
/>
<!-- build targets, each target can be called via "ant [name]",
e.g. "ant clean", "ant test j2mepolish" or just "ant" for calling the default-target -->
<target name="j2mepolish-init"
depends="init"
>
<property name="test" value="false" />
<property name="customization" value="" />
<property name="dir.work" value="build/real/${customization}" />
<property name="dir.dist" value="dist/${customization}" />
<property name="deploy-url" value="" />
</target>
<!-- In this target the J2ME Polish task is used. -->
<!-- It has 3 sections: -->
<!-- 1. The info-section defines some general information -->
<!-- 2. The deviceRequirements-section chooses the devices -->
<!-- for which the application is optimized. -->
<!-- 3. The build-section controls the actual build -->
<!-- process. -->
<target name="j2mepolish"
depends="j2mepolish-init"
description="This is the controller for the J2ME build process."
>
<j2mepolish>
<!-- general settings -->
<info copyright="Copyright 2006, 2007 Your Company. All rights reserved."
description="Please describe me."
infoUrl="http://www.j2mepolish.org"
jarName="${polish.vendor}-${polish.name}-${polish.locale}-ExpenseTracker.jar"
jarUrl="${deploy-url}${polish.jarName}"
name="ExpenseTracker"
vendorName="Enough Software"
version="1.0.0"
/>
<!-- selection of supported devices -->
<deviceRequirements if="config.active:defined and (test or enableCompilerMode)" >
<requirement name="Identifier" value="${config.active}" />
</deviceRequirements>
<deviceRequirements if="device:defined and (test or enableCompilerMode)" unless="config.active:defined">
<requirement name="Identifier" value="${device}" />
</deviceRequirements>
<deviceRequirements unless="test or enableCompilerMode">
<requirement name="Identifier" value="${devices}" />
</deviceRequirements>
<!-- build settings -->
<build fullscreen="menu"
symbols="polish.skipArgumentCheck"
usePolishGui="true"
workDir="${dir.work}"
destDir="${dir.dist}"
>
<!-- midlets definition -->
<!-- NetBeans defines this property automatically: -->
<midlets definition="${manifest.midlets}" if="manifest.midlets:defined" />
<midlets unless="manifest.midlets:defined">
<midlet class="ExpensesApp.Expenses" name="ExpensesTracker" />
</midlets>
<!-- project-wide variables - used for preprocessing -->
<variables>
<!-- Sample configuration options for J2ME Polish
<variable name="polish.TextField.useDirectInput" value="true" />
<variable name="polish.TextField.supportSymbolsEntry" value="true" />
<variable name="polish.MenuBar.useExtendedMenuBar" value="true" />
<variable name="polish.useScrollBar" value="true" />
-->
</variables>
<!-- Configure the customization settings here: -->
<resources
dir="resources/base"
defaultexcludes="yes"
excludes="readme.txt"
>
<root dir="resources/base/images" />
<root dir="resources/base/sounds" />
<root dir="resources/${customization}" if="build.${customization}" />
<root dir="resources/${customization}/images" if="build.${customization}" />
<root dir="resources/${customization}/sounds" if="build.${customization}" />
<!-- add the localization element for created localized
versions of your application:
<localization>
<locale name="en_US" />
<locale name="de_DE" encoding="utf-8" unless="test" />
</localization>
-->
</resources>
<!-- obfuscator settings: do not obfuscate when the test-property is true -->
<obfuscator name="ProGuard" unless="test" >
<!--
You can set additional parameters here, e.g.:
<parameter name="optimize" value="false" />
-->
</obfuscator>
<!-- log settings: only use debug setting when the test-property is true -->
<debug if="test" showLogOnError="true" verbose="true" level="error">
<filter pattern="de.enough.polish.example.*" level="debug" />
<filter pattern="de.enough.polish.ui.*" level="warn" />
<!-- example for writing log entries to the Recordstore Management System:
<handler name="rms" />
-->
</debug>
<!-- user defined JAD attributes can also be used: -->
<jad>
<attribute name="Nokia-MIDlet-Category" value="Game" if="polish.group.Series40" />
</jad>
</build>
<!-- execution of emulator(s) -->
<emulator
wait="true"
trace="none"
securityDomain="trusted"
enableProfiler="false"
enableMemoryMonitor="false"
enableNetworkMonitor="false"
if="test and not debug"
>
<!--
<parameter name="-Xjam" value="transient=http://localhost:8080/${polish.jadName}" />
-->
</emulator>
<emulator
wait="true"
securityDomain="trusted"
enableProfiler="false"
enableMemoryMonitor="false"
enableNetworkMonitor="false"
if="debug"
>
<!-- Attach the emulator to the NetBeans debugger: -->
<debugger name="antcall" target="connect-debugger" port="6001" />
</emulator>
</j2mepolish>
</target>
<target name="setdeploy"
description="Call this target first to set the OTA download-URL, e.g. ant setdeploy j2mepolish"
>
<property name="deploy-url" value="http://www.company.com/download/" />
</target>
<target name="enableDebug"
description="Call this target first to skip the obfuscation step, call the emulator and start the debugger, e.g. ant enableDebug j2mepolish"
>
<property name="debug" value="true" />
</target>
<target name="enableEmulator"
description="Call this target first to skip the obfuscation step and call the emulator, e.g. ant test j2mepolish"
>
<property name="test" value="true" />
<property name="dir.work" value="build/test" />
</target>
<target
name="emulator"
depends="enableEmulator,j2mepolish"
description="invokes the emulator"
>
</target>
<target name="clean"
description="allows a clean build. You should call [ant clean] whenever you made changes to devices.xml, vendors.xml or groups.xml">
<delete dir="build" />
<delete dir="dist" includes="**/*" />
</target>
<target
name="cleanbuild"
description="allows a clean build. You should call [ant cleanbuild] whenever you made changes to devices.xml, vendors.xml or groups.xml"
depends="clean, j2mepolish"
/>
<target name="debug" description="debugs the project" depends="enableDebug, enableEmulator, j2mepolish" />
<target name="deploy"
description="Deploys the applications. Currently empty."
depends="j2mepolish"
/>
<!-- NetBeans specific build targets: -->
<target name="run"
depends="enableEmulator, j2mepolish"
>
</target>
<target name="rebuild"
depends="clean, j2mepolish"
>
</target>
<target name="rebuild-all"
depends="clean, j2mepolish"
>
</target>
<target name="jar"
depends="j2mepolish"
>
</target>
<target name="jar-all"
depends="j2mepolish"
>
</target>
<target name="clean-all"
depends="clean"
>
</target>
<target name="deploy-all"
depends="deploy"
>
</target>
<target name="enable-compiler-mode">
<property name="enableCompilerMode" value="true" />
</target>
<target name="compile-single"
depends="enable-compiler-mode, j2mepolish"
>
</target>
<target name="connect-debugger">
<property name="jpda.port" value="${polish.debug.port}" />
<antcall target="nbdebug"/>
</target>
<target name="enableCustomization1">
<property name="dir.work" value="build/customization1" />
<property name="cfg.customization1" value="true" />
</target>
<target name="customization1"
description="customizes this project with the settings found in resources/customization1"
depends="enableCustomization1, j2mepolish"
/>
<target name="enableCustomization2">
<property name="dir.work" value="build/customization2" />
<property name="cfg.customization2" value="true" />
</target>
<target name="customization2"
description="customizes this project with the settings found in resources/customization2"
depends="enableCustomization2, j2mepolish"
/>
</project>
build.xml文件中最主要的是<info>,<deviceRequirements>和<build>三部分。
其中<info>元素指定说明了工程中的一般信息,如,工程名和版本。<deviceRequirements> 元素是用来指定程序编译时所选择的模拟器。<build>元素是工程编译构件时的主要控制器(如,可以设定属性 usePolishGui=”true”来指定把polish应用当前工程中,而设为false时,则说明当前工程不引入polish,此时工程与一般的 mobile应用程序一样)。
当build.xml文件中的<build>属性usePolishGui=”true”时,我们就可以修改工程目录中 resources里的polish.css文件控制程序的显示(美化j2me介面)。在j2me程序中只需要以“//#style”指令就可以调用相应的css属性(请注意这指令与注释“//”的区别)。其中,polish.css文件包含对应用程序的全部items和screens的style定义。
polish.css文件中常用的预定义的style(用于程序中的所有items和screens,但当引用自定义style时,预定义的style会被自定义style覆盖掉:
colors{}:用来定义一系列的颜色,供其它style中的color属性引用。
backgrounds{}:用来定义一系列的背景,供其它style中的background属性引用。
borders{}:用来定义一系列的边框,供其它style中的border属性引用。
focused{}:当获取某个item或screen的焦点时的style。
title{}:应用于所以screen中的title的style。
scrollbar{}:当build.xml文件中“polish.useScrollBar“变量设为true时被scrollbar引用。
label{}:应用于所以item或menu中标签的style。
以下style是当build.xml文件中“polish.MenuBar.useExtendMenuBar“变量设为true时被引用的:
menubar{}, menu{},menuItem{},leftcommand{},rightcommand{}
polish.css文件中自定义style:
注意:styel可以继承的,且引用子style时既保留父style的属性又有自己的属性,同时子style可以重写父style属性。
自定义style名称:如“.mystyle{}”是由点加字符串。注意不能是与预定义的名称相同。
下面我们来对ExpensesTracker中的UI---List以CSS进行修改。
修改后程序运行如下:
其polish.css文件:
colors {
fontColor: rgb( 30, 85, 86 );
focusedFontColor: #000;
bgColor: #eee;
focusedBgColor: #fff;
borderColor: fontColor;
focusedBorderColor: focusedFontColor;
}
focused {
margin: 1;
margin: 3;
background {
type: round-rect;
arc: 4;
color: focusedBgColor;
border-color: focusedBorderColor;
border-width: 2;
}
font {
style: bold;
color: focusedFontColor;
size: small;
}
layout: expand;
}
/**
* The title style is a predefined style which is used
* for all screen-titles.
*/
title {
padding: 2;
font-face: proportional;
font-size: large;
font-style: bold;
font-color: focusedFontColor;
border: none;
background {
type: vertical-gradient;
top-color: #fff;
bottom-color: rgb(140,206,220);
start: 10%;
end: 90%;
}
layout: expand|center;
}
.expenseList{
background {
image:url(BG.png);
color: rgb(184,235,246)
}
}
.expenseItem{
margin: 3;
padding-left: 3;
font-face: proportional;
font-size: small;
font-style: bold;
font-color: focusedFontColor;
focused-style: expenseItemFocused;
}
.expenseItemFocused extends .expenseItem{
background-color: argb( 150, 255, 255, 255 );
after: url(listItem.png);
layout:expand;
}
而Expenses.java中引用CSS的地方(绿色字体):
public Expenses() {
display = Display.getDisplay(this);
//get some play data
expenseItems = ExpenseInfo.LoadExpenses();
itemCount = expenseItems.size();
//Setup the UI
//#style expenseList
lsMain = new List("Expenses", List.IMPLICIT) ;
cmAdd = new Command("New", Command.SCREEN, 3);
cmEdit = new Command("Edit", Command.ITEM, 2);
cmExit = new Command("Exit", Command.EXIT, 1);
lsMain.addCommand(cmAdd);
lsMain.addCommand(cmEdit);
lsMain.addCommand(cmExit);
lsMain.setCommandListener(this);
//add all the Expense items to lsMain
rebuildList();
}
private void rebuildList(){
//add all the expense items to lsMain
for(int i=0; i<expenseItems.size(); i++){
if (expenseItems.elementAt(i) != null){
ExpenseInfo exp = (ExpenseInfo) expenseItems.elementAt(i);
//#style expenseItem
lsMain.append(exp.getDescription(),null);
}
}
}
相关推荐
2ME Polish 是用于开发J2ME应用的工具集: 从一份源代码中为多种设备和多种语言创建应用的建造工具(build tools)。 一个设备数据库,您的应用可以用它通过预处理为不同的手机进行调整. 一套用户界面(GUI), 可以在...
深入研究“j2me polish v212源码”,开发者不仅可以学习到J2ME应用开发的最佳实践,还能掌握跨平台移动应用的构建策略,对于提升个人技能和解决实际开发问题具有极大的价值。此外,通过阅读和理解源码,还可以为社区...
**Pro J2ME Polish** 是一个强大的开源工具集,专门用于提升Java ME(J2ME)应用程序的用户体验和视觉效果。...通过学习和掌握J2ME Polish,开发者不仅可以提升个人技能,还能为用户带来更好的使用体验。
**J2ME Polish入门教材详解** Java 2 Micro Edition(J2ME)是Java平台的一个子集,专门用于开发在小型设备和...通过深入学习和熟练掌握J2ME Polish,开发者可以提升其在移动领域的开发能力,为用户带来更优秀的体验。
通过学习和掌握J2ME Polish,开发者能够显著提升J2ME应用的用户体验,降低开发复杂性,同时也增强了在移动市场上的竞争力。无论是对于个人开发者还是企业团队,J2ME Polish都是一个值得投入的开发工具。
**学习J2ME Polish的步骤** 1. **理解MIDP**:首先,你需要对J2ME的MID Profile(MIDP)有基本了解,这是J2ME Polish的基础。学习如何创建MIDlet项目,以及如何使用MIDP提供的基本组件。 2. **安装和设置**:下载...
【标题】"Pro J2ME Polish 源码" 是一套专为 Java 二进制中间件(J2ME)平台开发的开源无线Java工具套件。它为开发者提供了丰富的功能,旨在提升J2ME应用的用户体验和外观,使之更接近桌面应用的水平。 【描述】...
《Pro J2ME Polish:开源无线Java工具套件详解》 在移动开发领域,Java ME(J2ME)曾是创建跨平台移动应用的主流选择,尤其在功能手机时代。Pro J2ME Polish是一个强大的开源工具,专为提升J2ME应用程序的用户体验...
针对这一趋势,开发者们利用Java 2 Micro Edition (J2ME) 平台,结合j2me Polish技术,构建了一款高效、便捷的移动客户关系管理系统(MCRM)。本文将深入探讨这个系统的开发背景、核心功能以及其在实际应用中的价值。 ...
为了深入学习J2ME Polish,你可以参考提供的"polish_book"压缩包中的文档,它可能包含了详细的教程、API参考和示例代码,帮助开发者掌握J2ME Polish的使用方法和最佳实践。 总的来说,J2ME Polish是J2ME开发者的...
现在好了,开源工具J2ME Polish 提供了针对这个问题的解决方案,事实上J2ME Polish为无线JAVA程序开发人员提供了一整套的工具。这些覆盖用于编译、预审核和打包程序的标准的工具,精致的可选GUI使你能通过一个简单的...
### 如何真正配置J2ME POLISH #### 知识点一:理解J2ME与POLISH的关系 在深入配置之前,我们首先需要了解J2ME(Java 2 Micro Edition)与POLISH之间的关系。J2ME是Sun Microsystems为嵌入式设备和移动设备设计的一...
J2ME Polish 游戏引擎为MIDP1.0的设备提供了完备的MIDP2.0游戏API。在这篇文章中,是从Robert Virkus的 Pro J2ME Polish 摘录的。你将学会通过设置各种预处理变量从而优化游戏引擎;在MIDP1.0平台游戏引擎受限的条件...
j2me polish cssj2me polish cssj2me polish cssj2me polish cssj2me polish cssj2me polish cssj2me polish cssj2me polish cssj2me polish css
【J2ME Polish环境搭建详解】 J2ME Polish是一款强大的工具,用于提升Java Mobile应用程序的用户体验,它提供了丰富的UI库和自动化编译、打包过程,使得开发者能够创建出具有现代感和高性能的J2ME应用。本文将详细...
J2ME Polish是用于快速开发J2ME应用程序的下一代框架。 包括的功能包括强大的GUI框架,实用程序类和用于创建设备优化应用程序的基于ant的构建工具。