基于RapidMiner开发问题和解决

file

RapidMiner(前身是YALE)是一个十分流行的开源数据挖掘软件,它不仅提供了一个GUI的数据处理和分析环境,还提供了Java API以便将它的能力嵌入其他应用程序。

BTW,选择RapidMiner而非WEKA的主要原因有两个:

1、RapidMiner对Java开发更方便

2、RapidMiner同时提供free license和commertial license,而WEKA只提供GNU license(无法用来开发商用软件)

本文记录了基于RapidMiner开发数据分析应用程序时遇到的一些问题和解决方法。

1、安装了RapidMiner 4.3,但执行RapidMiner.init()时抛出异常java.lang.UnsupportedClassVersionError: Bad version number in .class file

RapidMiner 4.3是用JDK1.6编译的(虽然用1.5也可以编译),因此在JDK1.5或以下版本环境里调用会抛出上述异常。解决办法有两个,一是安装JDK1.6,二是从CVS里下载RapidMiner的源代码自己在1.5里编译并导出jar文件。参考链接

2、在Eclipse应用里执行RapidMiner.init()时提示java.lang.IllegalArgumentException: URI scheme is not "file"

需要设置环境变量"rapidminer.home"到rapidminer安装目录,以便初始化时能找到"rapidminerrc"这个文件。即使未安装rapidminer,也要保证在这个目录下有个"etc"目录,里面有"rapidminerrc"文件。(另,还有个方法是设置"rapidminer.rcfile"环境变量指向rapidminerrc文件,未试验)

3、在Eclipse应用里执行RapidMiner.init()时提示[Error] Cannot find 'operators.xml'.

经过跟踪rapidminer代码,发现需要把operators.xml文件放在classpath下的com.rapidminer.resources包里。所以结合上面一条问题,可以执行的代码如下:

System.setProperty(RapidMiner.PROPERTY_RAPIDMINER_HOME, "D:/eclipse3.4m7/workspace/yale");
RapidMiner.init(); 

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2009/02/16/1392063.html

SWT里的GridLayoutFactory和GridDataFactory布局

我写的SWT程序里用到layout的地方大部分都是GridLayout,今天才发现原来从eclipse 3.2开始就有了这两个方便使的类:GridLayoutFactory和GridDataFactory。特别是GridDataFactory,以前要用至少三行的代码:

GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
txtName.setLayoutData(gd);

现在用一行就可以了(稍微长点儿):

GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(txtName);

或者有些情况下更简单:

GridDataFactory.generate(txtName, 2, 1);

顺便提一句:eclipse.org上关于SWT的例子在http://www.eclipse.org/swt/snippets就有很多,而JFace的例子则可以在这个地址(2015/10/20更新,JFace Snippets)找到(或者从cvs里下载)。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2008/12/09/1350938.html

Hadoop安装配置和使用问题记录

关于Hadoop如何配置的教程网上已经有不少了,配合hadoop主页上的说明,基本可以顺利在多台机器上配置好hadoop集群。这里记录的是我在实际配置和使用hadoop时遇到的问题,其中一些属于hadoop周边,如ssh配置时容易遇到的问题和解决方法,供大家参考。我目前是在windows xp里通过cygwin安装的hadoop,版本是0.17.2.1。

Cygwin部分

1、安装cygwin。

cygwin.com下载网络安装包,在选择组件的时候建议直接把openssh组件选中,有些版本的cygwin似乎不会自动安装diffutils组件,所以需要手工选中一下,否则配置ssh时会提示缺少该组件包。

2、cygwin控制台里的缺省提示符不太习惯

export PS1="u@w$"设一下好多了。

3、配置sshd

比较简单,可以参考这个链接。在ssh-host-config时问到Should privilege separation be used? (yes/no)时回答no即可,如果由于安全因素要回答yes时,在启动sshd时有可能遇到Privilege separation user sshd does not exist的错误信息,解决方法可参考这个链接

4、配置ssh使用证书方式自动验证

这里花了一些时间,后来觉得可能是由于机器上有两个版本的cygwin的缘故,因为在另一台机器上安装就没有出现问题。在使用ssh-keygen -t rsa命令后提示输入密码时,直接按两次回车即可。公钥的复制等过程这里不再赘述。

Hadoop部分

5、在Eclipse里运行hadoop的WordCount程序时提示异常:javax.security.auth.login.LoginException: Login failed: CreateProcess: whoami error=2

解决方法是把c:\cygwin\bin加入系统的path环境变量,然后重启Eclipse以便改动生效。

6、在Eclipse里运行WordCount时遇到java heap size不够的异常

在运行配置里加入-Xms200M就可以解决。(hadoop的helloworld要求的内存比较多?)

7、当要运行的运算依赖第三方类库时的问题

这个链接有所讨论,但暂时没看到除了在命令行里使用hadoop jar命令以外的解决方法,比如在0.17.2和0.18.1版本里我都没有看到JobConf类里有类似addJar()这样的方法,在JobConf#setJar()里使用逗号分隔多个jar文件的方式则会报找不到文件的错误。解决方式可能有两个:

  • a) 把所需要的第三方jar文件复制到每个节点机器的jre里(暂时没有试验)

  • b) 把第三方jar包和自己的类打到一个包里。

update: 在网上找到另一种方式,通过DistributedCache实现,原文里可能有笔误,我试验正确的方法是 调用DistributedCache.addArchiveToClassPath()方法,注意其第一个参数必须是相对路径,如/test/lib /my.jar,而不能是像hdfs://192.168.0.5:47110/test/lib/my.jar这样的绝对路径。关于DistributedCache的说明在里有一些。

8、调试mapreduce程序的方式

这个链接里讲得比较清楚了,因为很有用所以特意重复一次。如果文件存放在HDFS里,那么只需要调用JobConf#.set("mapred.job.tracker", "local")即可;如果文件也是存在本地的,还需要调用JobConf#set("fs.default.name", "local")方法。我通常让文件存在HDFS里调试,因为要使用本地文件要么参数需要改变,要么代码需要改变,维护两个环境很麻烦。在程序里用System.out.println()输出的内容可以在datanode的hadoop安装路径的logs/userlogs目录里找到。

9、使用自定义InputFormat时获取xmi:id

使用EMF模型元素作为key的时候,需要注意并不是在代码的任何地方都能得到xmi:id的值的。具体来说,在WritableComparable#write()方法里能得到(前提是该对象本来就有resource,即eobj.eResource()!=null),而在WritableComparable#readFields()里是不能得到的,在RecordWriter#write()方法里同样不能得到,因为后两者的EMF元素对象都是反序列化得到的,已经不是内存里原来的那个实例了。

10、map进行到100%后,reduce过程进行到某个数值(如16%)后就不再继续,直到被hadoop强制关闭。

在tasknode的log里记录如下:

2008-11-20 11:17:06,455 INFO org.apache.hadoop.mapred.TaskTracker: task_200811191041_0015_r_000000_0 0.16666667% reduce > copy (6 of 12 at 0.00 MB/s) > 
2008-11-20 11:17:09,455 INFO org.apache.hadoop.mapred.TaskTracker: task_200811191041_0015_r_000000_0 0.16666667% reduce > copy (6 of 12 at 0.00 MB/s) > 
2008-11-20 11:17:15,455 INFO org.apache.hadoop.mapred.TaskTracker: task_200811191041_0015_r_000000_0 0.16666667% reduce > copy (6 of 12 at 0.00 MB/s) > 
2008-11-20 11:17:18,705 FATAL org.apache.hadoop.mapred.TaskTracker: Task: task_200811191041_0015_r_000000_0 - Killed due to Shuffle Failure: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out. 2008-11-20 11:17:18,705 INFO org.apache.hadoop.mapred.TaskTracker: About to purge task: task_200811191041_0015_r_000000_0 2008-11-20 11:17:18,705 INFO org.apache.hadoop.mapred.TaskRunner: task_200811191041_0015_r_000000_0 done; removing files. 2008-11-20 11:17:18,705 WARN org.apache.hadoop.mapred.TaskTracker: Unknown child task finshed: task_200811191041_0015_r_000000_0. Ignored. 2008-11-20 11:17:40,845 INFO org.apache.hadoop.mapred.TaskTracker: Received 'KillJobAction' for job: job_200811191041_0015 2008-11-20 11:17:40,845 INFO org.apache.hadoop.mapred.TaskRunner: task_200811191041_0015_m_000011_0 done; removing files. 2008-11-20 11:17:40,845 INFO org.apache.hadoop.mapred.TaskRunner: task_200811191041_0015_m_000005_0 done; removing files. 

在我的java application的控制台里的输入如下:

08/11/20 11:06:39 INFO mapred.JobClient:  map 96% reduce 11%
08/11/20 11:06:40 INFO mapred.JobClient:  map 100% reduce 11%
08/11/20 11:06:43 INFO mapred.JobClient:  map 100% reduce 13%
08/11/20 11:06:47 INFO mapred.JobClient:  map 100% reduce 16% (在这里停很久) 08/11/20 11:17:12 INFO mapred.JobClient:  map 100% reduce 0%
08/11/20 11:17:12 INFO mapred.JobClient: Task Id : task_200811191041_0015_r_000000_0, Status : FAILED
Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out. 08/11/20 11:17:14 WARN mapred.JobClient: Error reading task outputnode2 08/11/20 11:17:14 WARN mapred.JobClient: Error reading task outputnode2 08/11/20 11:17:25 INFO mapred.JobClient:  map 100% reduce 16%
08/11/20 11:17:30 INFO mapred.JobClient:  map 100% reduce 25%
08/11/20 11:17:31 INFO mapred.JobClient:  map 100% reduce 100%
08/11/20 11:17:32 INFO mapred.JobClient: Job complete: job_200811191041_0015

我想找到这个问题的所在了。是secondary name node所在的机器没有配置dfs.http.address这个参数,该参数在hadoop-default.xml里的缺省值是0.0.0.0:50070,应改为name node所在机器的ip地址。参考链接

11、一些参考链接。

http://hayesdavis.net/2008/06/14/running-hadoop-on-windows/
http://hi.baidu.com/shirdrn/blog/category/Hadoop
http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop1/index.html
http://blog.ring.idv.tw/comment.ser?i=231

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2008/11/02/1325113.html

从google获得大尺寸地图图片文件

现在有很多工具可以从google地图获得大尺寸的地图图片文件,用于离线地图软件。这个地址介绍的方法我认为更加简单,而且同时适用街道地图和卫星地图,摘要如下:

1. 给你的firefox安装screengrab这个插件,这里是安装链接

2. 打开google地图网站,把地图定位到想要的位置(以中心点为准);

3. 点击地图右上方的“链接”链接,把弹出窗口里“粘贴 HTML 以便嵌入网站”里的内容复制下来并存成一个.html文件,如map.html,文件内容大概如下:

<iframe width\="425" height\="350" frameborder\="0" scrolling\="no" marginheight\="0" marginwidth\="0" src\="http://ditu.google.cn/maps?f=q&hl=zh-CN&geocode=&q=%E5%8C%97%E4%BA%AC&ie=UTF8&z=10&ll=40.037078,116.464691&output=embed&s=AARTsJrxRs93mjURz58t1CN5oqwlje5dZQ"\></iframe\><br /><small\><a href\="http://ditu.google.cn/maps?f=q&hl=zh-CN&geocode=&q=%E5%8C%97%E4%BA%AC&ie=UTF8&z=10&ll=40.037078,116.464691&source=embed" style\="color:#0000FF;text-align:left"\>查看大图</a\></small\>

4. 修改map.html文件的内容,把width和height改为所需要的大小,例如width="4000" height="4000"(注意,修改以后得到的地图的中心点座标是保持不变的);如果需要,还可以修改z值(缩放值),最大可以到17;

5. 在浏览器里打开map.html文件,即可得到一个显示大地图的网页;

6. 点击firefox状态栏里screengrab的图标,选择“Save->Complete Page/Frame”命令将整个地图保存为一个4000x4000的图片文件;街道地图推荐使用png格式,卫星地图推荐jpg格式,格式切换在screengrab的选项里改。(注意,0.95版的screengrab好像只能保存不超过9000x8000的图片,以后应该会修正)

file

图1 将浏览器里的大地图通过screengrab保存为图片文件

IBM DB2数据库若干问题和解决方法

用SQL实现交叉表格。

SQL Server里提供了Pivot关键字可以帮助实现交叉表格,但DB2里似乎没有等价的东西。实现的方法稍微复杂一点,以下是一个例子。

SELECT location,
MAX(CASEWHEN metric='PH'THEN value END) as PH,  
MAX(CASEWHEN metric='Hg'THEN value END) asHg,  
MAX(CASEWHEN metric='Fe'THEN value END) as Fe,  
MAX(CASEWHEN metric='Mn'THEN value END) as Mn  
FROM data_view  
GROUPBY location  

其中data_view表/视图有location、metric和value这三个字段,数据是下面这个样子:

location1    PH    1.142575278063135location1    Hg 0.0018310994140037379  
location1    Fe    0.2974983113601452  
location1    Mn    0.09548843270448454  
location2    PH    6.096025515217242location2    Hg 0.005575948698159294  
location2    Fe    0.32657056877142043  
location2    Mn    0.009418315198912612

得到的交叉表:

LOCATION   PH                           Hg                                 Fe                             Mn  
location1    1.1425752780631350.00183109941400373790.29749831136014520.09548843270448454  
location2    6.0960255152172420.0055759486981592940.326570568771420430.009418315198912612

"Error 500: DB2 SQL error: SQLCODE: -954, SQLSTATE: 57011, SQLERRMC: null"

APP Heap区不足,用DB2 UPDATE DB CFG FOR DBNAME USING APPLHEAPSZ 1024可以解决。注意要重启DB2以便让更改生效。

恢复(Restore)数据库

在控制中心里,选择数据库备份路径时要选到xxx.0的上一层,时间戳要与备份时一致(可通过查看备份路径里的文件夹和文件名得到,如20081007165742)。恢复数据库的命令行格式如下:

db2 restore <dbname> incremental from <imagepath> taken at <timestamp>

恢复数据库时提示“SQL2570N”

恢复数据库时提示错误信息,例如:

SQL2570N 由于操作系统不兼容或者指定的 RESTORE 命令不正确,所以在目标操作系统 "NT-32" 上从源操作系统 "AIX-32" 上创建的备份进行复原的尝试失败。原因码:"1"。

按照错误码(1)对应的用户响应,应该使用db2move实用程序:

要使用这个特定的备份映像,应在与创建该备份 时所在的操作系统“复原兼容”的系统上进行复原 。要将数据库从一种操作系统类型移至另一操作系 统类型,请使用 db2move 实用程序。要了解有关相互“复原兼容”的平台以 及 db2move 实用程序的详细信息,请使用诸如“跨平 台备份和复原”或“使用不同操作系统”之类的短 语来在 DB2 信息中心( http://publib.boulder.ibm.com/infocenter/db2luw/v9 )中执行搜索

参考链接:

Pivot Query
另一个方法(经实验不好用)
又一个方法(感觉比较复杂,没试)

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2008/08/19/1271120.html

启用EMF的自动生成UUID功能

缺省条件下,EMF不会为每个对象维护一个唯一的id,这在一些情况下不太方便,例如要在web环境下编辑一个EMF模型实例,通常需要在URL里传递对象的id以便确定目标。

有两种方式解决这类问题。第一种是在模型里给每个对象增加一个id属性,并维护使其保持唯一,例如在XXXFactorycreateXXX()方法里为这个属性赋值。

另一种方式是借助EMF的功能。其实EMF的XMIResource维护了一个id与对象的映射表,并且会为每个新创建的对象自动赋值,只要稍微设置一下就可以启用这个功能,具体的方法如下。

  1. xxx.genmodel里选中package节点,在属性视图里把Resource Type属性的值设置为XMI

file

  1. 重新生成代码,EMF生成的代码里会比原来多出XXXResourceImpl.java文件。

  2. XXXResourceImpl.java里,覆盖useUUIDs()方法,让其返回true(缺省返回的是false)。

  3. 重新生成代码。(删除以前的Manifest.MFplugin.xml文件以便这两个文件能得到更新)

这样,如果用文本方式查看新创建的模型实例文件,会发现每个对象都多出一个xmi:id属性,如xmi:id="_gitpslkoEd2PdI7FPnuunA"。要在程序里使用这个id,只需要用resource.getId(eobject)即可得到,其中resource可以通过eobject.eResource()很方便的获得。

参考链接

How To Enable UUID In EMF Generated Model To Get Copy&Paste Working
这个链接里的方法太麻烦了,但功效一样。

Eclipse GMF - Enabling UUIDs in Semantic model - The Simplest Way
GMF的时候这个链接里的方法应该比较方便

Eclipse 3.4新特性 – Plug-in spy

Eclipse 3.4提供了一个新功能:在任何界面下按Alt+Shift+F1 (Windows, Mac OS里用Shift+Option+F1),就可以看到Eclipse用来实现当前选中界面元素的类。

这个功能至少我看起来对插件开发人员很有用,因为当你想要模仿实现(或利用)Eclipse里的某个界面时,不用再像以前那样猜这个界面的实现类的名字了。比如最开始我就用了很久才找到属性视图的实现类是PropertySheet,而我总是朝着PropertyView的方向找,当然很难找到。

file

Plug-in Spy本是一个单独的小项目,在3.4里直接集成到workbench里了。

来源:Eclipse 3.4 Hidden Treasures

Cognos8安装使用问题记录

网上已经有很多关于cognos8的安装配置文章了(如这篇),这里介绍的是自己的亲身经历,供大家参考。以下是Cognos v8.3安装过程中遇到的问题和解决方法:

环境

Cognos v8.3

问题和解决

  1. 运行issetup.exe安装完成后,把cognos自带的jre里bcprov-jdk13-125.jar复制到机器缺省jre的相应目录下,否则运行Cognos Configuration会提示找不到类错误。

  2. Cognos8产品包括很多张安装盘(Image),BI Server包括最常用的功能,其他如Metric Studio、Framework Manager和SDK等等都需要在BI Server的基础上单独安装,这些component的安装也很简单,直接安装到BI Server所在目录即可。

  3. 在Cognos Configuration里启动Cognos Service时提示[ ERROR ] CFG-ERR-0103 Unable to start Cognos 8。只有使用cognos自带的content manager数据库时才报这个错误,改用SQL后错误消失。参考链接1(但后来测试中发现用SQL Server也会报这个错,怀疑有两个可能:1.数据库中未创建ContentStore所需的那些表,如果是这种情况,需要按cognos文档中的方法运行创建表的script命令;2.数据库使用的是Express版本,这种可能性较小,但如果是这种情况换用标准版就能解决;另,SQL Server Express版本的默认端口号是1702而非1433,在Cognos Configuration的Content Store里要注意正确配置)

  4. 为Metric Studio创建包时提示DPR-ERR-2014: Unable to load balance the request because no nodes in the cluster are available, or no nodes are configured for the service: metricsManagerService.
    解决方法:到Cognos Configuration里,在Cognos Planning这一项里,根据你的数据库类型新建一个resource,指向ContentStore那个数据库(也就是让这个数据库的配置与Content Manager下面的那个数据库配置一致),重启Cognos问题解决。

  5. 运行cognos sdk的jsp例子。要把$cognos dir$/sdk/lib下的xalan.jar复制到$cognos dir$/webapps/samples/WEB-INF/lib下,然后在Cognos Configuration里重启cognos,用http://localhost:9300/samples/index.jsp 就可以访问了。(cognos文档里说还需要在bootstrap_win32.xml里配置tools.jar的路径,我没配置好像也可以用,可能是有一些例子需要还没遇到)

  6. 启动report studio时提示HAL ERROR The web request failed. 12002 - Unknown URL: dialogs/_YU7.xml(解决方案探索中)

  7. 在工作区间里添加链接前要先设置Acceptable Domain列表,这是在Cognos Configuration的Cognos Application Firewall (CAF)里设置的,在Valid domains or hosts项里添加即可。

  8. 数据库里数据改变后,Report里的内容不更新。解决方法:这个问题可能是由于Cognos缓存了数据,要取消缓存,在Framework Manager里选择Project->Edit Govenors,勾掉Allow Usage of Local Cache选项,我试验的结果好像需要重新发布包并Update报表才生效。参考链接

  9. 把cognos报表集成到其他portal里。报表的地址可以在报表属性里找到,要去掉标题和工具条,可以加ui.header=false&ui.toolbar=false在URL里(cognos8.2里试验正确,cognos 8.3里可能要用cv.headercv.toolbar

  10. 在Transformer里更新一个powercube的时候,如果提示The locking of Cube XXX.mdc failed. It is probably in use by another application,可能是在浏览器里正在查看使用该powercube的报表,关掉浏览器过一段时间应该就可以正常更新了。

  11. 安装镜像名和component对应关系(部分):

    c8bisrvr_xxx -> BI Server
    c8bimodel_xxx -> Framework Manager, Map Manager
    c8bisamples -> (Samples)

Palm OS开发常见问题和技巧

  1. 判断当前focus是否为field
index=FrmGetFocus(form); if(index= =noFocus) return(false);
field=FrmGetObjectPtr(form,index);
  1. FrmDoDialog()使用方法:
FrmInitForm
FrmDrawForm set form controls
FrmDoDialog
read form controls
FrmDeleteForm 

注意:FrmDoDialog()无法获得frmOpenEvent。

  1. 测试控件类型:
switch (FrmGetObjectType(pForm, index)) { 
   case frmControlObj: 
   case frmFieldObj: 
   case frmScrollBarObj: 
   default:
}
  1. 在程序里使用标准的edit menu:

If your form has a menubar that consists of just the "Edit" menu, you can specify menu ID 10000 at form creation time. If your form has a menubar with several menus, you should specify your Edit menu like this, using PilRC notation:

PULLDOWN "Edit"
BEGIN
    MENUITEM "Undo" ID 10000 "U"
    MENUITEM "Cut" ID 10001 "X"
    MENUITEM "Copy" ID 10002 "C"
    MENUITEM "Paste" ID 10003 "U"
    MENUITEM "Select All" ID 10004 "S"
    MENUITEM "-" ID 10005
    MENUITEM "Keyboard" ID 10006 "K"
    MENUITEM "Grafitti Help" ID 10007 "G"
END

If you're using Constructor, just create an Edit menu with ID 10000, and the IDs for the items will be provided for you. http://www.palmoswerks.com/2001/11/16

  1. Push button的使用

GroupID若为0则与普通button一样,若GroupID不为0则同组内保证只有一个被选中。 FrmSetControlGroupSelection给push button赋值。

  1. 关于PrefGetAppPreferences

PrefGetAppPreferences要判断返回结果是否为noPreferenceFound

  1. 给文本框(Field)赋值
static void SetFieldText(FormType *form, FieldType *field, Char* value){
    MemHandle newTextH;
    MemHandle oldTextH;
    Char *text;
    newTextH = MemHandleNew(20);
    text = MemHandleLock(newTextH);
    StrCopy(text, value);
    MemHandleUnlock(newTextH);
    oldTextH = FldGetTextHandle(field);
    FldSetTextHandle(field, newTextH);
    if (oldTextH)  
        MemHandleFree(oldTextH);
    if(FrmVisible(form))
        FldDrawField(field);
}
  1. 关于CtlGetLabel()

如果需要CtlGetLabel(),则在CtlSetLabel()时不应立即释放Char*参数,否则CtlGetLabel()得到的将是乱内容。

This function stores the newLabel pointer in the control's data structure. It doesn't make a copy of the string that is passed in. Therefore, if you use CtlSetLabel, you must manage the string yourself. You must ensure that it persists for as long as it is being displayed (that is, for as long as the control is displayed or until you call CtlSetLabel with a new string), and you must free the string after it is no longer in use (typically after the form containing the control is freed). If you never use CtlSetLabel, you do not need to worry about freeing a control's label.

  1. 关于HideState()

HideState()返回代码之一是statXXX而非sysXXX,Palm SDK参考有误。

  1. 最好不要使用全局变量,用Feature代替之。

  2. Simulator没有截屏的快捷键,用Alt+PrintScr代替之。

  3. 让modal dialog全屏的方法

FormType* pOriForm = FrmGetActiveForm();
pForm = FrmInitForm(KeyboardForm);
FrmSetActiveForm(pForm);//Must
FrmSetEventHandler(pForm, KeyboardFormHandleEvent);

formWinH = FrmGetWindowHandle(pForm);
WinSetConstraintsSize(formWinH, 160, 160, 160, 240, 240, 240);
FrmSetDIAPolicyAttr(pForm, frmDIAPolicyCustom);
PINSetInputTriggerState(pinInputTriggerDisabled);
PINSetInputAreaState(pinInputAreaClosed);
SysSetOrientation(sysOrientationLandscape);
StatHide();
  1. 关于RepeatingButton

RepeatingButton响应CtlRepeatEvent而非CtlSelectEvent

  1. Palm simulator与电脑同步

可参考这个网址:http://duchaoqian.blogbus.com/logs/538520.html,注意电话号码用"00"

  1. 多行文本框

Multi-line的text改变内容后要FldRecalculateField(textField, false);否则换行可能不正确。

  1. 关于下拉列表

要产生popSelectEvent,在ctlSelectEvent里一定让handled=false

  1. 关于debug

遇到不知原因的死机等错误,最有效的解决办法是排除法,用if(false){...}不断缩小范围直到找到导致错误的代码。 按下按钮后,若模拟器不是崩溃而是没有反应,很可能是程序陷入了死循环。

  1. JPilotDB的使用方法

JPilotDB提供的lib文件太大,有4M多(因为包含了很多UI和相关lib),如果只是用于在Java里处理.pdb文件完全不需要它的全部内容,精简后的大小为96K,点击下载

代码范例:创建一个.pdb文件

try {
  //Construct the database
    PilotDBSchema schema = new PilotDBSchema();
    PilotDBDatabase database = new PilotDBDatabase("DB Name", "TypeID", "Creator", schema);
    for (int i = 0; i < 10; i++) {
        PilotDBRecord record = database.createRecord();
      record.setRecordData(new byte[]{});//set contents of the record
    }
    //Write to file
    FileOutputStream fos = new FileOutputStream("c:/test.pdb");
    database.write(fos);
    fos.close();
} catch (IOException e) {
    e.printStackTrace();
} catch (PalmDbException e) {
    e.printStackTrace();
}

代码范例:读取一个.pdb文件

try {
    //Read database from file
    FileInputStream fis = new FileInputStream("c:/test.pdb");
    PilotDBDatabase database = new PilotDBDatabase(fis);
    fis.close();
    //Read records of the database
    int recCount = database.getRecordCount();
    for (int i = 0; i < recCount; i++) {
        Record record = database.getRecord(i);
        byte[] bytes = record.getRecordData();
        //deal with the record
    }
} catch (IOException e) {
    e.printStackTrace();
} catch (PalmDbException e) {
    e.printStackTrace();
}

 19. 用程序控制退出当前运行的程序

EvtEnqueueKey (vchrLaunch, 0, commandKeyMask);
  1. Simulator里使用五维方向键(5-Way Navigator):
  • [Alt] + [Enter] = Select
  • [Alt] + [Left Arrow] = Left
  • [Alt] + [Right Arrow] = Right
  • [Alt] + [Up Arrow] = Up
  • [Alt] + [Down Arrow] = Down
  1. 关于Gadget。帮助文档里的例子可能比较旧了,回调(Callback)函数里的第一个参数FormGadgetType类型应改为FormGadgetTypeInCallback类型。此外,第三个void*类型的参数不能直接paramP->eType,要先转换为确定类型才能使用,例如在formGadgetHandleEventCmd里要先EventType* pToEvent = (EventType*) paramP;,然后才可以用 pToEvent->eType来判断事件类型。

  2. 在PODS里使用Palm OS Glue Library,除了在.c文件头部加上#include <PalmOSGlue.h>;外,还要设置这个project的linker配置,否则会提示"Undefined reference"。配置的方法祥见这里。摘抄如下:

    For managed make 68K projects, go to the project properties, and in the C/C++ Build panel, choose PRC-Tools Palm OS 68K Linker/General. Click the "New..." button in the Additional Libraries area, and enter this text into the dialog: -lPalmOSGlue; For a standard make 68K project based on the PalmSource template, in the file "makefile", modify the line for ADDITIONAL_LINK_LIBRARIES to read: ADDITIONAL_LINK_LIBRARIES = -lPalmOSGlue

  3. 判断Form里的对象是否可见:用FrmGlueGetObjectUsable()方法,注意要先加载Glue库。

  4. 根据新闻组里的言论以及自己的试验,FrmReturnToFrom(0)在Debug ROM里很可能有bug,会导致Simulator因内存问题崩溃。

  5. 若两个数据库的TypeID和CreatorID都相同,Palm将视其为同一数据库的两个版本,因此若要枚举出它们,DmGetNextDatabaseByTypeCreator()的第五个参数必须为false(有些应用可能恰恰不需要枚举出每个版本,而只需要最新版本,则应使用true)。

  6. 虽然数据库都是在内存里,但打开一个数据库的开销还是不能忽视,DmOpenDatabase()执行50次的时间大约有0.1秒。

  7. Palm SDK没有提供画圆的函数,可以用画圆角矩形的方法代替,让圆角的半径等于矩形边长一半即可。

  8. 关于使用表格控件的方法,这篇文章介绍的很详细,建议参考:http://www.mit.jyu.fi/~mweber/teaching/docs/palmos/book/ch08.htm

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2008/04/14/1152995.html

四种方法修改Palm Simulator使用的ROM

第一次运行Palm OS Garnet Simulator时,模拟器会提示你选择一个ROM文件,但这之后想换其他ROM文件时该怎么做呢?以下四种方法都可以实现:

  1. 在模拟器运行文件(palmsim.exe)所在目录找到palmsim.ini文件,修改里面的ROM项;
  2. 运行模拟器时加-rom参数;
  3. 启动模拟器时按住shift键,模拟器会像第一次运行一样提示你选择一个ROM文件;
  4. 在windows文件管理器里直接把ROM文件拖到palmsim.exe图标上启动。

来自Palm OS Tools Documentation。