2013年12月8日星期日

一年过去了

去年今日入此门,从此不问世间事。转眼一年已过去,何时出门看天下。

2012年12月22日星期六

我眼中的北京特色

办证和发票
十多年前到中关村,当时有名的高科技街区,感受最深的就是一条街上都在问你要不要光盘、办证或者发票,难免感慨这就是所谓的高科技?现在技术发展了,兜售光盘的早已不见了踪影,但是办证和发票的生意依然红火。
今天,从中关村一路走到国家图书馆,仍然是一路的办证和发票,每个发问的人怀里都抱着一个幼小的孩子,我猜测这是由于一旦被抓后会从轻处理吧。现在虽然还不是最冷的时候,但是白天气温也在零下几度了。这些妇女就抱着孩子在地铁口散乱的站成一排,站在地铁建筑的背阴里,晒不到阳光,可怜那些挨冻的幼小的孩子们。她们不断地跟路过的人们重复着"办证、发票",极少有人作出反应。但是可以肯定的是她们的努力也不会白费,因为我也在路旁看到一个年轻人和一个妇女正在一堆证件中翻找属于他自己的那张,这应该是圆满成交的结果吧。比这些妇女数量更多的是撒得遍地都是的名片,各种不同的版式,不同的电话号码,相同的就是醒目的"办证"等字样。一路上到处都是,数地铁站和公交站处最多。也许是因为这一路上都是学校吧,学校门口也不少。路过的时候,我在想是这是由于有需求才出现的么,是什么样的条件或者环境创造了这样的需求呢?

小食摊
人流多的地方就有不断办证和发票的吆喝声,也同样就会有一堆堆的小食摊,这也是在其他地方很难见到的。而在北京的地铁出站口这样的小食摊就很多,在今天路过的这一路,以前去过的三元桥、天通苑等都让人印象深刻。这些地铁出站口最惨不忍睹的就是地上的各种垃圾,多数是拜这些办证名片和小食摊所赐。当看到地铁出站口满目疮痍的情景,我实在难以承受自己知道有文明这个词。北京的地铁站里是极少有商品经营的,而在地铁外就不一样了,各种小食摊满满当当。毫无疑问,这更是因为有强大的需求了,同样,什么样的条件或者环境创造了这样的需求呢?前几天看到电视上报道说人们吃早餐难,很多早餐不卫生。即使是这样的早餐都来不及坐下吃,只能带着边走边吃,或者在路边冷风里,或者在公交车或地铁里。这些在其他城市我很少看到的场景,在这里我看到了,我认为这是特色。

2012年7月9日星期一

Delphi多线程自定义消息丢失

我们的程序中有一个BUG,偶尔的时候程序没有按照正常的工作流程继续,所谓卡在了某一位置。
查看代码和日志后发现,工作流程的驱动是通过PostThreadMessage消息到主线程来进行的,当程序卡在某一位置时,消息是发送出去了,但没有到达消息处理函数中。所谓消息丢失了。
PostThreadMessage确实可能会使消息丢失,函数说明中明确提到了。所以更换为PostMessage,发消息到TApplication的Handle。但是消息丢失的情况更加频繁了。
看来利用TApplication来处理消息也不是好办法;只有把消息发送到主窗体,在主窗体中处理消息应该更加可靠。
虽然Delphi的帮助里对 TApplication的Handle说明是"Provides access to the window handle of the main form (window) of the application.",但是我们应该知道,这里的main form和Delphi程序里我们的主窗体是不一样的,尽管我们在Delphi的Project属性中设置时也是称作Main form。我们的设置的主窗体,在TApplication中是MainForm,我们的主窗体的Handle也只能用MainForm.Handle来获得。
最终解决,PostMessage消息到MainForm.Handle,然后在MainForm中进行处理,终于和谐了。

2012年7月1日星期日

不同浏览器在中文输入过程的细微差别

之前在使用QtWebkit的时候发现它对中文输出控制上跟其他浏览器有一点儿小的差别。现在就Chrome、Firefox、IE9简单对比一下对中文输入过程的处理。
打开一个包含文本输入框的网页,启用中文输入法,鼠标点击输入框,输入几个字母(输入法状态栏出现待选词,但还没有确认输入),在这时以三种方式失当前输入框失去焦点,一种是点击网页上空白区域,另一种是点击地址栏,最后一种是点击其他程序的窗口。
对于第一种方式,三种浏览器的行为是一样的,都是输入框失去焦点,输入法取消输入过程。
对于第二种方式,Firefox和IE9也都是取消输入过程,而Chrome却是把输入的字母当作键的内容填到了输入框,也就是说输中文输到一半的时候,失去焦点时会把刚才键入的字母当作输入内容。
对于第三种方式,Firefox和IE9都是保留输入法状态,当再切回时,仍然可以接着刚才未完成的输入过程继续按键;但是Chrome的行为却跟第二种方式时一致,把键入的字母当作输入内容填入了输入框。
可以看到Firefox和IE的行为是一致的,而Chrome有些不同。

2012年6月30日星期六

Git/Delphi/Bat自动化构建

最近重拾Delphi,开工的首件事情就是实现自动化构建。
沿用N年以前的方法,直接使用批处理脚本实现。对于一个小项目的自动化构建过程,无非就是取代码、编译、打包、测试等过程;对于大多数项目,恐怕连测试也没有,例如我现在做的这个。本来这些都是简单的东西,没啥需要多说的。只是这是第一次在Windows下使用Git,而且在编译时对Delphi工程的版本号进行了修改,所以简单记录一下。

1. 取代码并获取版本号
Windows下在命令行使用Git,最好是生成一个.sh脚本。所以取代码就用三行命令搞定。
ECHO git pull >> pull.sh
pull.sh
del pull.sh
获取版本号,在使用 Git 生成编译版本号这篇文章的基础上根据需要修改一下就好了。

2. 修改版本号
其实每次构建需要修改的就是版本号a.b.c.xxx中的xxx,让xxx与代码仓库中的revision对应起来,这样方便版本管理。
Delphi工程的版本信息是记录在资源文件中的,默认为与工程名同名的res文件中,是编译过的资源文件,不能直接修改。要想修改Delphi工程的版本号,可以在IDE中进行修改,这样就很不方便实现自动化构建过程中去修改版本号。记得以前在公司项目组的构建人员为了实现修改Delphi工程的版本号,用AutoIt3写了一个脚本,用Delphi的IDE打开工作,然后点击菜单、按钮等等,费尽了力气。
其实可以用另一种方式来解决,Delphi工程中可以包含多个资源文件,可以把版本信息放入一个单独的资源文件,使用文本格式保存,即rc文件,在编译前使用资源编译工具编译成res。具体为:
a. 创建一个version.rc,写入版本信息
b. 每次构建前使用脚本修改version.rc中的版本号,并编译version.rc生成version.res
c. 在Delphi工程中引入版本信息资源文件 {$R version.res version.rc}
d. 在Delphi工程属性中版本信息标签页中的包含版本信息选项去掉
使用以上步骤就可以方便的使用脚本修改版本号,完成自动化构建了。


2012年2月23日星期四

一次软件冲突的解决过程

这几天看完了调试九法,是本好书,只是道理该懂的人自然会懂,不懂的看了书也不会懂。
于是想起了几年前工作中遇到的一些问题,算是属于广义的调试吧。

有一次项目组收到技术支持人员的报告称,客户(一所学校)的机房安装过我们的软件E后,他们原来上课使用的教学软件K,就不能使用了。随后,我就收到了去现场解决软件冲突的任务。
到了学校的机房,我们先把所有计算机都启动,软件E和K都是开机就自动运行的,但是发现我们的软件E都正常启动了,而软件K却只有几台正常启动了,其他的都没有在运行。
接下来,我把一台软件K没有正常启动的计算机上的软件E卸载掉后,重新启动,发现软件K还是没有成功运行。
我们又卸载掉几台计算机上的软件E后,把所有计算机重新启动,发现还是装了软件E的计算机上软件E都正常运行了。但是,软件K还是只在几台计算机上启动成功,这些计算机有的装有软件E,有的并没有安装软件E。由此,我们判断,软件K是否能够运行,和安装软件E没有关系,也就是说软件E和K本身并不冲突。
但是,客户的机房确实是在安装完我们的软件E后才出现问题的,而且这期间没有安装过其他软件,计算机上也有还原保护系统在工作。
我再一次把所有计算机重新启动了一次,还是只有几台计算机上软件K在正常运行,而且每次重新启动后能正常运行软件K的计算机也不相同。正当百思不得其解的时候,我突然发现虽然软件K正常启动的计算机和前一次不同,但是它们的座位号却是一样的。我赶紧查看了所有能正常运行的软件K的座位号,发现它们的座位号都是不同的。我找到软件K保存座位号的注册表项,在软件K不能正常启动的计算机上去查看,发现注册表项中的值与已经运行的某个软件K的座位号是相同。到这时就很确定是软件K的座位号设置重复才导致了它不能正常启动的。于是,我们修改了一些重复的座位号后,重新启动计算机,这些计算机上的软件K也能够启动了。
这时,我几乎可以确定是安装我们的软件E的时候,机房管理员使用了系统同传的方式,就是在一台计算机上安装好后,然后把整个系统克隆到其他计算机上,导致软件K的座位号设置重复。机房管理员最终也确认了这一点儿。
最后,我们把所有计算机的软件K的座位号设置正确后收工。

其实以上过程还算不上有条理,所以效率不是很高,加上计算机上有还原卡,每次修改注册表项前都需要打开还原卡,修改后再设置还原卡。整个过程花了几个小时。
确定软件E和软件K本身并不冲突是一个分界点,此后就只在软件K的找原因了。
发现软件K的座位号设置也是比较偶然的,因为我们对软件K并不了解,它是其他公司开发的,之前我们并没有使用或看到过。虽然我们最后发现了座位号的问题,但是如果去询问软件K的技术支持人员可能他们会在第一时间就给出检查座位号设置的建议,因为他们更理解系统。

2011年11月14日星期一

与用户的连续三次沟通

昨天晚间,一位老师在使用我们的网站应用时,连续几次电话和我沟通。
第一次,她说无法添加评阅内容,添加评阅内容的输入框不会出来。我询问了她的电脑的操作系统和她使用的浏览器,得到的回答是遨游浏览器,只能很抱歉的让她换用其他浏览器,因为目前我们的网站不支持遨游浏览器以及其他等等安全的浏览器,我们只支持Firefox、Chrome和IE7以上浏览器。
第二次,她说换了浏览器,可是仍旧无法添加评阅内容。我猜测她想添加评阅的位置不对,我告诉她只能在原文上进行划词后,然后输入评阅内容;而她希望是像Word一样批注。
第三次,她说系统自动生成的评阅内容不能删除,我告诉她删除按钮在右侧;系统自动生成的评阅和她自己添加的评阅都可以删除的。

以上说明:
1. 我们的产品是有很多问题的(浏览器兼容、易用)。
2. 用户是不会去看使用指南的(在告诉用户可以使用产品的邮件中都附带了使用说明的,而且对上述所有问题都有讲述;整个文档共七页,大部份页面是截图)。
3. 现场用户的声音很重要,产品验证应该提前,在正式开发前就要请用户来验证设计。

几次通话后,本没有想到太多。后来看到《启示录》里对于产品设计验证的建议,就我目前手头的几个产品来讲,确实很有感触。

2011年9月13日星期二

悲剧的网络

Gmail等于连不上了,将就着用紫狐打开也是奇慢无比。VPSYou也很适时的发来邮件,说机器挂了,只能备份数据退款处理。更不用提下班后回到租住的房子里那让人断念的长宽。悲剧的网络,悲剧的网络时代!

2011年8月17日星期三

Excluding Operation For Multiple-Choice Items In Computer-based Test




Multiple choice is a popular item type in computer-based or internet-based tests. Its implementation and operation is so easy and straightforward that nobody need more instructions. However, some skills we used in paper-based tests cannot be applied to computerized tests. Excluding is just one of these. In a paper-based test, one can draw a slight line on the options to indicate the option is not the favored answer. How to provide this facilitation in computerized tests? It's a good idea to use right mouse-clicking for this function. Thus, we have two operations for the choice option, one is left click to choose it as the answer, the other is right click to exclude it as a distractor. And an option will have three states: normal, chosen as answer, excluded as distractor. We can draw a table about these states and operations.

state operation output
normal left click chosen
normal right click excluded
chosen left click chosen
chosen right click excluded
excluded left click chosen
excluded right click normal


green arrows indicate left clicks
red arrows indicate right clicks

As shown in above table, whenever left-clicking an option will lead to choose it as the answer - keeping the choosing operation straightforward, while right-clicking has a bit more functions. When the option is excluded, right clicking on it again will change it to normal state, otherwise to excluded state. Maybe a simple state transition diagram will make things clear. All left-clicking arrows point to the chosen state and all right-clicking arrows point to the excluded state except one started from itself, the last one arrow give a chance to change the option from excluded to normal. The states, operations and transitions make a simple and powerful design for computerized multiple choice items.

Question 1: Why not change the option to normal when right-clicking an chosen option?
Answer: Because we never provide a way to undo the choosing, we don't want to give the user more things than excluding. All new things is excluding and undo the excluding.

2011年7月12日星期二

空调(出现)之前

当我第一次看见空调的时候,就想这绝对是最愚蠢的发明。前几天在The New Yorker上看见了这么一首诗。

Before Air-Conditioning

by
Frederick Seidel

The sweetness of the freshness of the breeze!
The wing is wiggling the trees.
The sky is black. The trees deep green.
The man mowing the enormous lawn before it rains makes goodness clean.
It’s the smell of laundry on the line
And the smell of the sea, brisk iodine,
Nine hundred miles inland from the ocean, it’s that smell.
It makes someone little who has a fever feel almost well.
It’s exactly what a sick person needs to eat.
Maybe it’s coming from Illinois in the heat.
Watch out for the crow, though
With them around, caw, caw, it’s going to snow.
I think I’m still asleep. I hope I said my prayers before I died.
I hear the milkman setting the clinking bottles down outside.

2011年4月30日星期六

公司与椅子

昨天在列表里看见一个觉得很无聊的问题,问有哪些公司难进,值得进,正准备屏蔽掉的时候,发现一帮人随后开始讨论公司与椅子的问题了。其中有人说选公司很简单,去面试的时候看看他们坐什么椅子。确实,我上学时觉得对于程序员来说最累的是屁股和眼睛,所以一定要有个好的椅子和显示器。实验室当初装修的时候,买的300多的椅子,虽然说不是什么太好的东西,可感觉比那些小椅子舒服多了。等毕业到了公司,我有时候会拿公司的椅子和显示器说事,那种小转椅,旧的CRT显示器,好不容易换液晶显示器了,居然是个1366*768的18.5寸的憋屈玩意儿。记得转正的时候,主管问我有啥意见,我直说硬件比较差,在追问之下,我干脆就说显示器和椅子。看来,椅子确实不是对公司的偏见了。终于,我又回实验了,当然跟椅子没太大关系。看来对于某些不知道员工为什么要离开的老总们,先把公司的椅子换换吧。

2011年3月30日星期三

折腾

这一年来没少在折腾。最近发现折腾出了几根白发,而且似乎大有星火燎原之势,难怪某日梦见已然银发满头,真是未卜先知哪。
昨天又有前公司的领导同事过来请吃饭顺带一个主要任务是邀我回去继续做同事,虽然理性分析给出的条件还不错,但是我想我还是会做非理性的选择,至少在看得见的一两年内还得继续折腾。
地球离了谁照转,他说出来的,我深感同意。机会只是瞬间的,不会为谁停留。留给我的还是折腾。

2011年2月7日星期一

春节假期过去了

因为放假前事情太多,家里房子又刚刚装修,所以这个春节没有回去过年了。这是我第二次没有回去过年了,上一次是98年1月地震后。

这几天除了休息、工作,还尽情地玩了几个晚上魔方,发现虽然忘了几个公式,但是速度却比以前稳定了,50次平均成绩终于进了26秒,如果再想提升,就必须有目的的加以练习了。

这几个下午,还去城隍庙和文化宫去猜了几回谜语,在城隍庙时遇到一个高中生,跟他一起猜谜。今天下午去文化宫去猜谜语,猜了十几个,得了一双手套、水笔、铅笔袋什么的,结果灯谜协会的看我对猜谜语挺感兴趣,就邀我周末有空的时候过去一起玩,还留了联系方式。回来的路上还冥思苦想了几个计算机相关的谜语。我知道自己属于瞎猫逮死耗子的那种,完全业余,所以回来搜索了一下灯谜协会的活动,顿时觉得自己的文学与知识面都太弱了,还是老老实实写代码吧。

继续老老实实写代码,马上春节假期就结束了。

2011年2月4日星期五

魔方界杂感

在等待Android SDK下载的空当,手里转着魔方,想起好久没到魔方吧去看看了,不知大过年的有啥活动没。打开论坛却发现了已过半年的一次事件,老瓦被WCA禁赛三年。为了了解下事情经过,进而翻了好多旧贴,看到了很多东西,连同之前自己的一些想法,整理一下。

规则
翻看了论坛里相关的贴子,仍然是一团糊涂。既然WCA已经出结果了,那就按规则来吧,反正大家参加的都是WCA的比赛,那就只能按WCA的规则来办事了。感觉老瓦的行为是有些过了,但是我却不认为这是单一的原因。经历了南京赛的最小步风波,再看这里到处提到的一轮还是两轮的赛制,真是觉得无奈。如果说最小步风波是比赛规则的漏洞可能被利用了,那么赛程的不确定性就是这次事件的导火索了。数次比赛的安排给参赛者的意思都是看时间吧,如果时间允许都安排两轮。如果说大家在赛程上没有分歧的话,就不会把矛盾积累到这么深。所以,比赛规则和赛程还是事先确定,跟大家明确讲清楚了比较好。
我觉得WCA虽然是个有规则的组织,但它并不是一个专业的机构,所以能做的事情很少,即使在这些冲突的处理中,也只能是从主办方和WCA代表处了解些情况。现在比赛举办的越来越多了,主办方应该先把规则和赛程定好,以避免类似的事件。

商业
魔方这么火热,最开心的就应该是魔方厂家了,当然,也没啥太开心的,因为靠这东西发大财还是很难的。但是,随着魔方的继续升温,比赛越来越多,规模肯定也会越来越大,那样,看中商业机会的也许是不仅仅是几个魔方厂家了,也许还会有其他厂商。这样,魔方中的商业气氛就会变浓,冠名、代言、赞助这些形式的广告宣传也一定会影响主办方及参赛者。为了避免因商业化而引起的与运动本身的冲突,更应确定好比赛的基本规则,将比赛限定在一个基本的框架内。外围事物可以丰富广阔,但不应影响到运动本身。看到占星拒绝春晚的机会的时候所写的东西,很佩服他的想法,尤其是提到不能让魔方奥数化。

魔方
我很佩服国内魔方厂家的创新精神。国甲二加入了轨道,尺寸小了那么一点儿,感觉顺手多了,我现目前用的还是两年前从老张那里买的国甲二,后来又买了若干各式魔方,都没觉得这个顺手。国甲五干脆把每个块的大小都做了变化,初次试用,真是爱不释手。现在大雁孤鸿凌云又深得大家喜爱。不过,随着魔方热,背后的专利问题很可能会困扰各魔方厂家。

真想不到,一个小小的魔方,引出了这么多事。魔方界在不知不觉中形成了。

2011年1月7日星期五

Sikuli X 之 如何创建GUI单元测试脚本

Sikuli集成了jUnit,所以支持图形用户界面的单元测试。在Sikuli IDE中通过快捷键 Ctrl-U或者菜单View下的Unit就可以打开单元测试面板。

Sikuli IDE旨在尽力减少代码输入,所以在Sikuli IDE中,一个继承自junit.framework.TestCase的Python类会自动生成并把你的单元测试脚本包起来。

通常,一个单元测试脚本包含有构造和析构函数,分别是setUp()和tearDown(),还包含一堆以test为前缀的测试方法。

单元测试脚本的基本结构如下:
 def setUp(self):  openApp("AnyRandom.app")   wait(SCREENSHOT_OF_THE_APP) # wait until the app appears  def tearDown(self):  closeApp("AnyRandom.app")   untilNotExist(SCREENSHOT_OF_THE_APP) # wait until the app disappears  def testA(self):  ....   assert exists(PICTURE_THAT_SHOULD_BE_THERE)  def testB(self):  ....   assert not exists(PICTURE_THAT_SHOULD_NOT_BE_THERE)

要运行单元测试脚本,需要点击单元测试面板上的“Run”按钮,而不是普通的运行按钮。

另外,也可能从命令行使用选项 -t test-script来运行单元测试脚本。


是软件就会有BUG

为了证明是软件就会有BUG,把翻出来的几张旧图贴贴。请看红色圈。

标题是"讨好主人",内容却是买好友。
<a href="http://blog.boyue.info/wp-content/uploads/2010/12/friendbuy.png"><img class="alignnone size-medium wp-image-38" src="http://blog.boyue.info/wp-content/uploads/2010/12/friendbuy-300x201.png" alt="QQ 讨好主人是买好友" width="300" height="201" /></a>

反过来的BUG也是可能的。
<a href="http://blog.boyue.info/wp-content/uploads/2010/12/qqfriend.png"><img class="alignnone size-medium wp-image-44" title="qqfriend" src="http://blog.boyue.info/wp-content/uploads/2010/12/qqfriend-300x197.png" alt="QQ 买好友与讨好主人" width="300" height="197" /></a>

主窗体状态是在线,任务栏图标却是离线。
<a href="http://blog.boyue.info/wp-content/uploads/2010/12/qqstatus.png"><img class="alignnone size-medium wp-image-39" src="http://blog.boyue.info/wp-content/uploads/2010/12/qqstatus-171x300.png" alt="QQ状态" width="306" height="450" /></a>

还有某些时候出现的 第22页/总21页,数数确实是个难题。

2010年12月29日星期三

Sikuli X 之 Region类相关说明

PSMRL:指可以把模式(Pattern)、指向图像文件名的字符串或者表示纯文本的字符串(string )、匹配(Match)、区域(Region)或者位置(Location)作为参数进行传递。

PS:指可以把模式(Pattern)、指向图像文件名的字符串或者表示纯文本的字符串(string )作为参数进行传递。

applicable for Screen or Match or Screen and Match:尽管区域(Region)的所有方法可以用于显示器(Screen)类和匹配(Match)类的对象上,但是每个方法在这些类上都是合理的(例如:Screen(0).below(),find(PS).setRect(rectangle))。所以,如果提及它,就表示在应用场景中这个方法在屏幕对象或者匹配对象上使用是合理的。

Note on Multi Monitor Environments:在多于一个显示器被激活的情况下,想要对非默认屏幕(这种情况下是主显示器)上的区域进行操作,要考虑一些特殊因素。所以,在多于一个显示器的环境下开始使用Sikuli之前,要先阅读多显示器环境相关章节。

2010年12月28日星期二

Qt单实例运行

程序要求单实例运行,且如果第二次运行激活已存在的程序实例的窗口。
于是有了下面的这段代码。

QSystemSemaphore sema("sema", 1, QSystemSemaphore::Open);
sema.acquire();
QSharedMemory mem("memObject");
if (!mem.create(1)) {
HWND w = FindWindow(NULL, "Window Title");
if (w)
{
SetForegroundWindow(w);
ShowWindow(w, SW_SHOWNORMAL);
}
sema.release();
return 0;
}
sema.release();

神奇的是的Qt里,只写ShowWindow是不行的,如果窗口最小化后再从另一个实例中激活它,窗口上的控件得不到绘制。可能是Qt的消息处理函数进行了判断吧。而且必须得在ShowWindow之前调用SetForegroudWindow。

2010年12月24日星期五

Sikuli X 之 Region类

区域(Region)就是屏幕上的一个矩形部分,它由位置和维度确定。位置 (x, y) 就是它的左上角相对于屏幕左上角的距离;维度 (w, h) 就是它的宽和高。
其中 x、y、w、h是以像素为单位计算距离的整数值。

区域(Region)只知道它在屏幕上的位置和它的维度,并不知道任何它的可视内容(窗体、图片、图形、文本等)。

新的区域(Region)可以在已有的区域基础上创建:你可以在各个方向上扩展区域或者获取相信区域,直到屏幕的水平或者垂直边界。

区域(Region)上的可视内容和文本内容可以使用像find()这样的方法计算得到,find()方法在区域搜索一个给定的矩形像素模式或者文本串。区域中进行匹配的内容有一个在0到1之间的相似度,0就是没有找到,1就是找到了且它的每一个像素都与模式精确匹配。可以让find以一个最小的相似度进行搜索,这样一些形状和颜色的微小变化就可以被忽略。如果不指定其他东西,Sikuli将以最小相似度0.7进行搜索,通常的情况下这样做与预期相符。

查找(Find)操作返回一个匹配(Match),它具有一个区域(Region)拥有的所有属性和方法,可以以相同的方式使用(比如查找或点击它里面的另一个目标)。匹配(Match)包含了搜索中使用的模式的维度,它也知道模式被发现的位置以及相似度。有一个区域保存了最后一次成功的查找操作中最佳的匹配和最后一次成功的findAll()返回的所有匹配(通过getLastMatch()/getLastMatches()获取)。你可以使用wait()等待模式出现,使用waitVanish()等待模式消失,或者只是使用exists()检查一下模式是否存在,这样就不用处理异常(当模式不存在的时候,exists()返回None,而不是抛出异常)。

Sikuli X支持可视化事件驱动编程。你可以告诉一个区域来观察某些东西的出现、消失或变化。这就有可以等待一个观察结果的完成或者让它在后台运行,而你的脚本继续执行。当这些可视化事件发生时,你脚本中的处理器就会被调用。每个区域有一个观察者,每个观察者可以处理多个可视化事件。停止观察是你的责任。

你可以通过模拟鼠标和键盘行为在一个区域上操作。你可以选择在先前查找操作中计算出的区块内操作,也可以一个将被隐含查找的模式上操作。要想模拟像游戏或者图形这样的特殊应用程序中的复杂操作,有低级的鼠标和键盘操作可用。

想支持更复杂和健壮的脚本,你可以处理FindFailed异常,当查找操作失败会将会抛出它。

在同一个区域上的操作,可以使用Python的"with"语句进行分组。

Screen是继承了Region类的所有属性和访求的另一个类。通过Screen类,你可以获取屏幕维度和不同的显示器(如果你有多个显示器)。如果你不指定区域,它也给了你一个默认的区域来操作。通常在你对整个屏幕进行搜索的时候,仍需要写region.find(image),只是这里的region是整个屏幕。所以为了方便,如果只写find(image)将简单的在整个屏幕中操作(实际上是默认/主要的屏幕),而不用每次都指定默认的SCREEN。而另一面,这样做将降低搜索速度,因为在整个屏幕上查找目标是耗时的。所以,为了提升处理速度,写region.find()能把搜索限定在指定的更小的矩形内(通常是你感兴趣的应该程序的主窗体)。另外,可以使用setROI()把随后的查找操作在比整个屏幕更小的区域中。