CS巴别塔(1)

说说用户界面那些事——鸣雷篇

Posted in Uncategorized by Kenny Yuan on 2012/01/10

聪明的一休哥片段

一休哥提问:这些界面设计有什么共同之处?

图像

小叶子回答:So called “Hermann Grid Illusion”

参考:

Advertisements
Tagged with: , ,

说说用户界面那些事儿-银杏篇

Posted in Uncategorized by Kenny Yuan on 2010/09/19

汽车驾驶员需要专注,肯定不能边开车边看电影——就连打电话、发短信造成的事故都挺高发的,更别提电影了,这是在NHTSA有数据可查的。所以车载系统的屏幕,为了安全,最好也只显示枯燥的导航地图。但是乘客们不这样想,乘客们会想要利用车载系统来娱乐,比如看看电视、放放电影什么的。无奈安全第一,于是在常见的设计方案中,车载系统会“贴心地”在行驶中关闭娱乐功能,只允许使用地图功能。

但这个方案并不怎么高明:除了专业司机,很少有人会坐在停驶的车上看几小时的电影,而行驶途中的乘客则是最无聊的——跑长途时,行车几个小时太平常不过了,连续几天每天跑十个钟头的也很常见,就说在北京城内,堵俩钟头也算稀松平常的——这就让用户花高价买来的车载娱乐系统成了摆设(什么QNX什么WINCE的高科技RTOS,都是骗银滴)。这时候,可能有些负责任的厂商就会开始教育用户了:“just don’t sit in that spot——我们不是提供了后座上的车载娱乐系统了么?您倒是坐后座上去啊?”于是,当两人旅行的时候,如果乘客们不想在车上无聊,就会发生“妻离子散、劳燕分飞、两地分居、君在奔驰头我坐奥迪尾”的问题。而且因为无人陪同,驾驶员更容易疲倦,也就有可能造成更高的事故率——那可真是“撒手人寰、驾鹤西游、尘归尘土归土、生死相隔解愁肠”了。

在我往下接着侃之前,请读者您花10分钟细细考虑一下这些场景,并试着找一找技术上的解决方案……

梅赛德斯在08年发布了一项名为SplitView的技术(官方中文名称为“分屏视图”,是联合BOSCH做出来的),请看视频:http://www.5min.com/Video/Mercedes-Benz-SplitView-Tech-Review-259734353

大概地解释一下:司机在左边,看到的画面是导航地图;乘客在右边,看到的画面是电影。电影的声音可以外放(比如演唱会之类的还是可以让驾驶员听听的),或者也可以将声音全部输送到乘客的无线耳机上。所有的中控台按纽都是给驾驶员用的,控制的是导航画面等功能。乘客使用一个独立的无线遥控器来控制娱乐功能。嗯……遥控器?

Remote Click

Remote Click

我想,看过了视频之后,关于这个系统的优劣,聪明的读者你一定已经有所体会,我就不多评价了。这个系统的原理也很简单:从像素上来讲,那个显示屏是“双份”的,所以画面都是同时显示的(并非分时)。只不过两份画面被分别限制了可视角度,估计是利用了裸眼3D之类的技术,但是设定了不同的研发目标而已。

本文没有末尾的总结,因为读者们总是最聪明的 🙂

Mercedes Benz Splitview官方图

Mercedes Benz Splitview官方图

Ctrl + X, Ctrl +S; Ctrl +X, Ctrl + C …

Tagged with: , ,

说说用户界面那些事儿(第三部分)

Posted in Uncategorized by Kenny Yuan on 2010/09/12

这真是一个最好的时代,也是一个最坏的时代:优秀的用户界面全都相似,差劲的用户界面却各有千秋——但无论如何,一个优秀的计算设备必须要有一个优秀的用户界面,这是放之四海皆准的事实。好的用户界面是设备的生命之光、欲望之火种源,同时也是设备的罪恶……

——哦,对不起,我不是文学青年,不能引用太多的“名著”开头,这部分文章里,我得继续讲科学定律……截止到目前为止,本系列文章仍然在介绍小学文化程度的基础知识,没有侃大山,也就没有切题(因为题目叫《说说用户界面那些事儿》,典型的侃-able title)。所以我尽量压缩内容,尝试在本篇内结束这些没人爱看的基础知识介绍,从下篇开侃。

嗯,虽然我很想压缩内容,但是有一个新的变化:我终于又回归到了机械键盘一族(Cherry的青轴)。虽然在twitter上我不是像某些同学那样不管什么样的鸡毛蒜皮的小事都要不停地推啊推啊的那种话痨但是有了这块超级好用的每按一次键就发出清脆的响声让人感觉打起字来就像弹钢琴时用上了节拍器一样合谐的Cherry机械键盘之后我发现我打字的欲望开始变得异常地强烈了起来甚至达到了一句话竟然可以写出上百个字都没有标点符号的程度而且整个句子都只是没多少意义的文字而已似乎只是为了打字而打字这一个单纯的目的而已了——嗯,话说小时候写作文的时候也是这样凑字数的。

——常看网络小说的你一定知道的:以上段落作废……(并非只有起点的大大们才能享有这种权利)

Cherry青轴机械键盘

Cherry青轴机械键盘


(2.3) Hick-Hyman Law (希克海曼定律)

常有脑残批评我的思想太阴暗,为什么不忽略那些负面的东西,只看那些伟光正的。从这个角度来说的话,此系列的前两篇文章恐怕也太“负面”了。所以我来写点光明的、令人振奋的东西,同样的,它还是科学定律:

——嗯,以上段落仍旧作废。下面我来介绍一个科学定律:Hick-Hyman Law (希克海曼定律)。

T = b * log2 (N + 1)

其中,N是选项个数,b是可以用经验法测量的常量,T是做出选择所需要的时间。

这个定律说明,当选项的个数以线性增长时,在若干个选项中作出选择所需要的时间是以对数曲线增长的。换句话说,选项的数目在快速增长的时候,做出选择所需要的时间只是在慢慢地增长。假如选项的数目增长了250倍,所需的时间也仅仅是增长了8倍左右。在前面一句多余的解释之外,还有一个多余的图表用来解释:

从图中我们可以看出,如果你弄了许多的菜单项出来,用户肯定会受到困扰,操作时间会变长。但是操作时间的增长数量,和菜单项数目的增长数量相比,基本上可以无视了。

Maya的PieMenu里有很多选项


关于这个定律,其实还有一些可以深入的话题,还可以扯到认知科学和神经网络。但我一来懂得不多,二来不想浪费太多篇幅,所以就到此打住——嗯,有话痨趋势的我在此不得不多说一句,研究HCI一定要懂一些Cognitive Sciences(认知科学),不用精通但是怎么也得懂一些基础。比如:Change Blindness, Inattention Blindness和IOR之类的……


(2.4) Power Law of Practice (实践的幂定律)

古人云,常言道,俗话说,曾子曰,Confucius he say:“包子有肉不在摺儿上”……哦,错了,应该是“一回生、二回熟”(所以,摺上有肉的包子不能只蒸一回,嘻嘻)

——以上段落作废。

我们都有过这样的体会,在最开始做一件事情的时候,往往需要集中全部精力,但往往还做得不够好,比如骑自行车/学开车,或者解数独,或者打地鼠,或者玩Super Mario Bro——还记得你第一次上手红白机的时候么?在控制Mario向前跳跃的时候,你有没有把手柄当成了WII手柄来用?后来当你可以不用Konami Code也能全八面迅速通关的时候,你肯定不会再把游戏机从桌子上扯下来了吧?

Super Mario Bro


上上下下左右左右前前后后


Power Law of Practice (实践的幂定律)

T = a * N ^ (-b)

其中,N是练习的次数,T是第N次的完成时间,a和b是常数。

这个定律的意思是:随着练习次数的增加,完成相同任务所需要的时间是指数下降的,参见下图:


有了这样的一条定律,对我们来说无疑又是一大利好消息——哪怕一个任务设计得很糟糕、很耗时也不用太担心,只要用户多加练习,那么用户完成任务的时间就会大幅下降,而且是迅速地大幅度下降。

如果你想验一下Power Law of Practice,可以先找一个秒表(或用手机功能/手机App),开始计时,然后清空你的浏览器的内容缓存、所有保存的表单内容、所有保存的密码、所有的URL历史、所有的Cookie,然后记录下所用的时间。然后再重新开始并计算时间,如此重复若干次,然后画图。

如果你多注意观察,在以下这些电脑用户的身上也能观察到Power Law of Practice的效果:超市收银员、银行柜员、照相馆里PS一寸免冠照片的操作员、电脑城装机器的技术员……

虽然有Power Law of Practice的保驾护航,但是,我要说“但是”:一般在设计一个普通操作的时候,最好也不要超过3次鼠标点击。这并不是一个科学定律,只是一个经验公式;而且它也不是普适的,只是针对一般性的普通操作。举个例子来说:一个频繁更新的软件,如果在下载完更新包后,一定需要用户的操作才可以实施更新,那么,最好能让用户在三次鼠标点击之内完成这一次更新。(联想一下JRE Update/Adobe Update/iTunes Update/Windows Update,再对比一下Google Chrome这种不需要任何鼠标点击的)

嗯,接下来我的恭喜作为读者的你,看了我这么多枯燥的说教竟然还没有被吓跑,其实我还有心介绍一些更多的理论上的东西,比如GOMS/MTM之类的,但一来那只是一种测量方法,二来做科普时基本上无法夹带我的私货(嗯,开篇说过了,我自己在做的一个基于手势的HCI,暂定名为WheelUI),三来有许多有意思的东西如果不“先下手为强”,估计别人慢慢地就都知道了(那样子就无法完成ZB伟业了)……呵呵,你看我写了这么多理由,就是为了能够到此为止,点到为止,从些不再写知识点,继而进入侃大山的历史新篇章…… History became legend; legend became lenovo… until, when chance came, a new era had begun… And a brand new saga is being written…

谢谢观赏,下次再见!



00:00:25,469 --》 02:45:35,634
<font color="#ffff00"
反义:Sharon桶 盆泥
脚对:大妈 杀啦
世间粥:歪脖子的小马,不拉屎皮特



(以上是字幕组加上的一大堆乱七八糟的文字,我从来没有看懂它们的意义,请不要跨服务器追捕)






Tagged with: ,

说说用户界面那些事儿(第二部分)

Posted in Uncategorized by Kenny Yuan on 2010/06/29

(2.2) Steering law (转向定律)


书接上回……嗯,上回书说到:十位英雄正在青楼之上饮酒吃菜,忽听得“噔噔噔噔”有人上楼,直惊得十位英雄是苶呆呆发楞!要问来者何人?嘿嘿,我就是不说……

可Fork的岔口: http://en.wikipedia.org/wiki/Steering_law

在本章开始处,已经列出了即将要写的一些“定律”。我想好奇心强的人应该已经wiki+google过了。所以,如果在内容上本文无法胜出,那么就算白干了。嗯,多说一句:如果为此就故意在前面隐藏不写,也是没用的,因为wiki+google仍然会把这些“隐藏”的东西带给人们。所以关键还是content, content, content. (语感好的同学会知道这三个词应该怎么读)

Steering Law(转向定律)这个名字来源于汽车转向。根据中国特别色,可能用Handlebar Law(拐把定律)更合适一些——谁让我们是自行车大国呢?为了理解这个定律,设想你要通过一个又长又窄的隧道,对汽车来说这隧道是2米多宽(或者对自行车来说是两尺多宽),你敢用多快的速度通过呢?如果这隧道是20米宽,你敢用多快的速度通过呢?(注:关于速度/速率这样的名词问题,在这里就不细究了;另:一提到Steering就想到“外内外”的同学,请去找Stig切磋)

慢慢拖吧,撞坏了赔不起

慢慢拖吧,撞坏了赔不起


Steering Law在“隧道”为矩形的时候,其数学形式为

Steering定律: T = a + b * ( A / W )


其中的T是到达目标的时间,a和b还是常量,A是走过的路径的长度,W是矩形隧道的宽度。

Steering定律图解

Steering定律图解

(Steering定律还有一个通用的“计算器”形式,路径宽度用函数来描述,本文就不涉及了,还是矩形的好理解)


这个公式表明:路径越短,到达目标的时间就越短;隧道越宽,到达目标的时间就越短。联系前文的例子,这是符合生活经验和直觉的。

Steering定律是根据Fitts定律推导出来的。在应用Fitts定律分析的时候,如果对用户的输入所经过的2维空间上的路径有要求,就需要考虑Steering定律了,比如前面分析过的Pie Menu,就不能忽略Steering定律——Pie Menu项目的宽度 really matters(不过不能用矩形隧道的简化形式,呵呵)。


Steering Law实例分析1:神秘的三角区域

在此文中有一个很好的实例,我就直接给出链接了:http://www.scsblog.cn/articles/fittslaw.html (简体转贴版,底下有原文链接,懂繁体的可以去看原文)


Steering Law实例分析2:杯具的DataTip

Visual Stuio 2005的DataTip功能是一个不错的设计,当鼠标指针指向一个变量后,就会出现一个DataTip来显示它的内容,并且通过点击加号,还可以把变量的成员展开。这是个方便操作的好设计,但在某些情况下,它也会成为杯具,见下图(点击图片可以看100%全图):

谁能点到最左端那个加号

谁能点到最左端那个加号

想要点击加号,鼠标就只能横移,上下都不能出界太多。否则DataTip会被关闭,只能重头再来一次。虽然上图中的数据和变量是专门为了演示而编写的,但是在实际调试中,这样的超长DataTip也很常见。

应用Steering Law来分析,我们会发现这个“隧道”的宽度W太小了,如果增大宽度W,就可以使操作更方便。增加宽度的效果可以用下述实验来体验:在DataTip弹出之后,在DataTip上的任意位置点击鼠标右键弹出菜单,这时DataTip就会被“冻结”在屏幕上,然后我们就可以经过任意路径移动鼠标到加号处,此时的W是一个相当大的值(超过一个屏幕的高度)。

(注:DataTip的加号并不一定非要点击,用鼠标指向这个加号也能展开成员。减少点击次数也是一种提高易用性的方式,后面会有内容专门谈这个问题)


实例分析3:人人都恨滚动条

不管是用手,用笔,还是用鼠标,使用滚动条都是一件很不爽的事情。之所以这么说,是因为以下的这些原因,以垂直滚动条为例:

问题1:滚动条的水平宽度很小,从当前鼠标位置移动到垂直滚动条上,平均移动距离D大约是半个屏幕,而W则是非常小的一个值(20个像素以下)。按照Fitts定律,这样的移动,效率不高(对于最大化的窗口,如果屏幕的最右边也计入滚动条的区域,则会大大改观W值)。
问题2:很多人不知道滚动块是可以拖、滚动条的空白区是可以点的,他们只会点击两端标有箭头的按钮。这两个按钮很小,不好定位。如果当前视图在文档中占的比较很小,可拖动的滚动块也会非常地小(还是Fitts定律)。
问题3:对滚动块进行拖动的时候,如果在水平方向上鼠标位移大于5~6倍的滚动条宽度,滚动块就会跳回原来的位置。应用Steering Law来分析,宽度W虽然有所提高,但仍然不够大。
问题4:滚动条能指示视图在文档中的位置和比例,但无法提供与内容相关的滚动信息(嗯,Chrome的搜索结果指示算是一个特例)。当然这一条不是用Fitts/Steering定律来分析得到的。

(写这段文字的时候,我坐在办公室,听着四面八方传来的“哗哗哗”的滚轮的声音)

作为对比,我们来考查一下iPhone触摸屏上的滚动:不管是单指还是双指滚动,都是对几乎所有可视区域可用的。此时的W=屏幕宽度(或几乎等于屏幕高度——对于水平滚动)。如果你有iPhone,请回想一下这种操作或者直接体验一下,比如故意斜向滑动手指,来滚动重直内容(测试宽度W)。

图:iPhone滚动“条”,WP7的滚动“条”

(另:对于有索引的内容,一个可以操作的指示器会比滚动条更有优势,比如各种通讯录界面中的A-Z指示器)


虚拟的宽度W:辅助和宽容

让我们再回过头来考查Steering定律:汽车通过狭窄的隧道,速度肯定会降下来,可火车却能很快通过。这中间的区别当然不是因为火车司机不怕死,而是在于火车有铁轨,铁轨限制了火车的方向,不会让它“出轨”撞到墙上(再比如拓海的排水沟过弯)。

拓海的排水沟跑法

拓海的排水沟跑法

同样的道理,在绘图程序中,如果想用鼠标绘制一条水平直线(同样,不深究“直线”和“线段”这样的名词区别),相当于让鼠标指针通过一个高度为1像素的横向隧道。这种操作非常困难(用直尺比着鼠标都很难做到,不信你试)。所以在绘图程序中会提供一种“限制”功能,限制鼠标只能水平或者垂直运动(或者加上四个斜45度方向共计8个方向),这就相当于把汽车变成了有铁轨的火车来通过隧道。Photoshop移动物体时的Shift键限制也是同理。在分析Fitts定律时,我们认为屏幕边框代表了一个相当大的宽度W;同理,我们可以认为,在这些例子中Steering定律的隧道宽度W也是一个相当大的数字,所以最终时间T可以很小。


离开鼠标屏和触屏,在有实体的交互中,这种增大W的方式依然存在。汽车的人机交互界面一般称为HMI(人·机器接口)。在汽车的HMI中,也包括一些电子交互系统,比如Audi的MMI和Bimmer的iDrive,通过屏幕和旋钮/按键来进行交互。Lexus的Remote Touch用的则是力回馈控制杆和按钮。假设屏幕上有两个选项,那么你在拨动控制杆的时候,会感觉到控制杆不是可以连续搬动的,而是有两个很明显的“档位”;如果屏幕上有三个选项,那么就会有三个“档位”,以此类推。这种交互设计,通过“档位”的辅助,为运动轨迹增加了辅助(Steering定律的W),同时也增加了目标物体定位的宽容度(Fitts定律的W),最终使得用户能快速操作,并且不用集中全部精力在屏幕上,最终提高了驾驶安全性。

Lexus的Remote Touch

Lexus的Remote Touch

Lexus Remote Touch的Screen

Lexus Remote Touch的Screen


如果你认为这种带回馈的控制杆还不算实体交互,那么可以考虑一下汽车的换档杆:

手动换档杆

手动换档杆


不管是鼠标屏、触屏,还是刚买回家的新电器,对于同样的操作,熟手和新手的完成时间大相径庭(想想你的父母第一次用iPhone的时候误拨了多少次电话出去?或者你多久才教会他们用一件新电器?),各位看官,这——究竟是为何——呢?……嗯,欲知此中的规律,且听下回书——分解——


扩展阅读&扩展练习

上次写的内容,在结尾处扔了一堆扩展阅读和扩展练习,感觉有点像讲课了(要知道我很讨厌老师的——所以我这回装得像说书的)。所以,这次的文章取消这两部分——当然,我并没有拦着你使用大脑和google,对不?


更新关于触屏的触感:2011 CES上露面的TeslaTouch是一个伟大的发明,它的网站是:http://www.teslatouch.com/ 大约来说,它看起来是一个普通的触屏,但是能够在指定的区域提供指定的触感,开发人员可以将屏幕上的内容和屏幕的触感结合起来,有一个演示的例子:屏幕上显示的是结冰花的玻璃,当你的手在上面摸的时候,会有类似冰花的触感;你摸过的区域会显示为透明的玻璃,这时候再去摸这个区域,它就是玻璃的触感了——还记得iPhone上的iSteam程序么?很明显,这个冰花程序要比它cool多了:) 另外,那些靠马达震动的触屏,比起来简直就是XXXXX(省略140字)。最后多说一句,这个TeslaTouch的名字也揭示了它的原理,详见它官网中的PDF 🙂




Tagged with: , ,

说说用户界面那些事儿(第一部分)

Posted in Uncategorized by Kenny Yuan on 2010/06/24

(读者请跳过本段括号内的文字:经常来骂人的那位同学,您请回吧,每回都那么激动,别气坏了身体,要知道,这篇文章的ZB程度可是很严重的……)


第一章:可跳过不看的前言废话


之所以写这个文章,是因为最近在做一个基于手势的人机交互项目(自费的个人项目,暂定名为 #WheelUI)。


见过很多别人写的类似文章,都会讲自己“当年从低级到高级走过来的每一步”(往往还要提到ABC/XYZ等对新人来说很生疏的名词术语,外加感叹当时的条件有多艰苦),可我偏不愿意写那样的八股——我只想写一点可能对别人有用的知识、经验以及感悟,和一条可能的未来之路。


标题中使用UI而没有用GUI,是因为在通常的概念中,GUI一词和WIMP绑定得过于紧密。WIMP是指基于Window Icon Menu Pointer(窗口/图标/菜单/指针)的界面,这些东西是197x年在Xerox PARC搞出来的,在198x年苹果去挖了一批人做出了第一台Mac,之后微软也去挖了人搞出来Windows,后来Windows几乎一统江湖。不过近些年苹果又咸鱼翻身搞起了GUI的革命,主要武器就是Multi-Touch(多点触摸)。Multi-Touch和WIMP一样也不是苹果的原创,这两者的历史都可以追溯到197x年。以下是一些知识链接:


WIMP: http://en.wikipedia.org/wiki/WIMP_(computing) Please Note: P本来是Pointing Device,本文中我用了Pointer。
Multi-Touch in Wiki: http://en.wikipedia.org/wiki/Multi-touch
还有Bill Buxton写的一个综述: http://www.billbuxton.com/multitouchOverview.html
Bill Buxton也是Xerox PARC出身的,是Multi-Touch的先驱人物: http://en.wikipedia.org/wiki/Bill_Buxton
这里是他的专栏: http://www.businessweek.com/bios/Bill_Buxton.htm
从Market Value这个角度来说,Apple的咸鱼翻身相当成功:http://news.bbc.co.uk/2/hi/business/10168684.stm



早年的Apple MAC上的GUI

早年的Apple MAC上的GUI



Xerox Star 8010

比Apple更古老的GUI



多点触摸的用户界面可以直接用手指点被控目标,相比使用鼠标间接输入算是前进了一步,但总会有人不满足:“还有没有别的方式可以人机交互?”说到这里可能有些人已经明白,我要说的其实不是UI而是HCI,只不过是HCI这个词在中文圈子里没人青睐,为了让更多的人听明白只好改说UI。
HCI: http://en.wikipedia.org/wiki/Human-computer_interaction


本文就是想要说说用户界面HCI那些事儿。


注:关于上文中对苹果的创新的“贬低”,我想声明一下:口口相传的段子会把创新的“前传”全部剔除,只剩下一个孤独的英雄人物。想要了解更多?推荐去看一本叫做《创新的神话》的书,或者从google开始。另外还需要声明的是:将某项技术推广到全世界,同样是功劳大大地有,我一点我从不否认。



Xerox PARC外观

Xerox PARC外观

(图片注解:多年以后,当榨布丝和给慈站在行邢队的面前,肯定会想起当年他们参观Xerox PARC的那个下午。当时,PARC是一个……)



第二章:用户界面的科学定律(Laws of HCI)



作为正文的第一部分,一定要有一个好的开始。最近的CVPR2010上,有人用CV机器学习的方式来检阅论文质量,达到的效果是“以拒绝15%的正样本为代价,可以滤除一半的负样本”(http://dahuasky.spaces.live.com/Blog/cns!1AB3BC993DB84FD7!1168.entry)。为了能够看起来像一篇好文章,我打算在这一章要介绍几个科学定律,大致有以下内容:Fitts’s Law, Meyer’s Law, Steering Law, Law of Crossing, Hick’s Law, Power Law of Practice等。


(2.1) Fitts’ Law (费兹定律)


(友情提示:在此处可以fork,但欢迎继续阅读本节中的实例分析和后面的内容 http://en.wikipedia.org/wiki/Fitts’_law


通俗来讲,Fitts定律是用来计算在目标已知的情况下,直线移动鼠标指针到目标所需要的时间的定律,它的数学表示形式如下:

Fitts定律:T = a + b * log2 (D/W + 1)


其中T是完成移动所需要的时间,a和b是常量,D当前指针距离目标的距离,W是目标的宽度。或者更精确地来说:

图解Fitts's Law中的变量

图解Fitts's Law中的变量


T = 平均完成移动的时间
a = 启动设备需要的时间常量
b = 设备固有速率的一个时间常量
D = 当前指针位置到目标的中心位置的距离
W = 在移动方向上目标的长度,或者是判断指针是否已在物体上的宽容度(比如针对1像素的点,设计宽容度为5*5=25个点,这时水平移动的W=5)


Fitts不仅仅是对鼠标移动任务起作用。触摸屏/键盘/其它硬件等,只要涉及到人机界面和人的操控动作,都适用Fitts’ Law。


对于使用者来说,时间T越小表明当前的操作越快捷。时间T和很多因素有关,从数学式中不难看出它们的含义(请注意其中的线性/对数关系)。之所以说Fitts定律是科学定律,因为它提出了预测,并且有实验证伪的可能。在实际的实验中,Fitts定律和实验结果吻合得很好、很精确。


举一个最常见的例子来解析Fitts定律:如果想要关闭窗口,你需要把鼠标指针移动到窗口右上角的close按钮上(很显然这是在说“低级”的Win32 GUI):
a = 你用手去抓住鼠标的时间;或者:已经抓着鼠标的手,从静止状态启动进入到运动状态的时间;
b = 和鼠标速率反相关的时间系数,速率越高,时间系数b越小。
D = 当前的鼠标指针位置到close按钮的直线距离。距离越短移动得就越快(时间T就越小)。
W = 红色close按钮的size,一般是20多个像素见方。很明显它的个头越大越好找到(时间T也就越小)。


从上面这个鼠标指针的例子,我们也能发现Fitts定律的所存在的问题:
Fitts定律问题1:它只适用于单个直线方向上的时间计算;(2D空间上的后文后谈到)
Fitts定律问题2:在鼠标的应用研究中,如果有鼠标加速度,它就不适用了;
Fitts定律问题3:如果用户经过了多次训练,它也变得不适用了(下面有一个小节将要讨论这个问题)


在实际使用中,有许多人用下述方式来关闭已经最大化的窗口——他们用鼠标狠狠地向右上角一甩,之后鼠标指针就一定是位于屏幕的最右上角了,这个位置虽然看上去不在close按钮范围内,但是它仍然被视为在close按钮内部——如果考虑一个虚拟平面的话,其实这时候鼠标指针的位置早就在屏幕之外了,但因为屏幕实际空间有限,所以鼠标指针被限制到了屏幕右上角。此时Fitts定律仍然有效:只要将W视作非常大的一个值即可(甚至可以比屏幕还大),于是套用公式时会发现T值最终很小,这正好与实际情况相符。

虽然看上去鼠标没有在关闭按钮上,但实际上却可以关闭窗口

虽然看上去鼠标没有在关闭按钮上,但实际上却可以关闭窗口


根据Fitts定律,我们不难推出以下结论:


Fitts定律推论1:可操作元素(如图标)需要有合适的大小,太小的话操作会变慢(W变小,T就变大);
Fitts定律推论2:如果可操作元素布局合理,可以更迅速地操作,因为D变小,T就变小;
Fitts定律推论3:Popup菜单比窗口上方的下拉菜单好使,因为D变小,T就变小。(注:D并不仅仅是对指针来说的,如果为了弹出Popup菜单,需要另一手的配合运动,那就是另外一回事了——除非熟练掌握了键盘,否则另一只手的启动时间a往往是一个不小的数值)
Fitts定律推论4:屏幕的四个边缘和四个角落是非常容易找到的位置,比如在Win32下,最大化状态的窗口,其关闭按钮非常容易找到,就是因为它利用了屏幕角落(W变得很大,甚至超过了D,此时T会很小)。Mac的下拉菜单容易找到,也是同理。


应用Fitts定律分析Pie Menu


下面我们利用Fitts定律来考查一种设计:Pie Menu (http://en.wikipedia.org/wiki/Marking_menu)


Pie Menu也叫Radial Menu,它类似于右键弹出菜单,但是它的每个选项是一个扇形,最中间的“Pie Hole”(不是骂人)被用来直接关闭Pie Menu,参见下面的示意图:

Pie Menu示例

Pie Menu示例


或者一个实际的例子:

Pie Menu实例

Pie Menu实例


从Fitts定律的角度,我们很容易发现Pie Menu的优点:
Pie Menu优点1:移动到每个选项的时间都很短,因为D很小且W较大
Pie Menu优点2:经过处理,可以使W变得更大(超过屏幕大小),这样就更方便操作——只需要限制鼠标指针不得离开Pie Menu即可达到此效果(后面有个例子要说到这一点)
Pie Menu优点3:如果Pie Menu是误触发,关闭它的时间是接近零的常量


Pie Menu在实际中


(示意图)罗技的MouseWare驱动中的Pie Menu

(示意图)罗技的MouseWare驱动中的Pie Menu

后来版本的“Web风火轮”

后来版本的“Web风火轮”

第一个版本虽然是方的,不是Pie,但使用起来其实更方便:当鼠标中键(滚轮)按下的时候,会在当前鼠标位置显示3×3网格的的Pie Menu,鼠标位于正中央,点击中间的cell可以关闭Pie Menu。其它8个cells代表了8个功能,这8个方向非常容易区分,很难混淆。并且无论鼠标实际移动了多少距离,它都会被限制在这3×3的网格中,不会离开(这就使得公式中的W变得相当大)。

除了“第一次点击呼出,第二次点击执行”这样的两次点击的方式,这个Pie Menu还有如下的操作方式:如果鼠标中键按下但并未抬起,然后移动鼠标到相应的cell,此时再抬起鼠标,同样可以激活该cell代表的命令。整个过程变为:按下->移动(在某方向上移动任意距离)->抬起,一气呵成。


可以想像,如果右上角的cell的功能是关闭窗口,这个方式会比点击窗口上的关闭按钮要方便许多。后来版本的“Web风火轮”花哨了许多,但也变得不实用了,因为8方向的Pie Menu非常容易找到cell,而更多的方向则不那么好控制,毕竟在这时候的指针移动是2维的,而不仅仅是沿着一条限定好的直线进行(见前面的Fitts定律问题1)。本文后面的章节会谈到Steering Law,这个定律就是Fitts’ Law在二维平面上的形式。



文章内容已经很长了,先写到这里吧,待续 🙂





——————

注1:Fitts’ Law的标准译法不详,见过有一个人翻译成“费兹”,于是就这样写了。其文章的URL是:http://www.scsblog.cn/articles/fittslaw.html (简体转载本)。在这个文章里作者也举了一些例子。不过不如我的例子用得好,嘻嘻……


注2:还有一个Meyer’s Law也试图建立类似的模型:

Meyer定律:T = A + B * Sqrt (D/W)


其中:
T = 移动到目标的时间
D = 当前位置和目标的距离
W = 目标的宽度(或容忍度)
A 约为 -13 msec
B 约为 108 msec



扩展阅读

除去前文中已经给出的链接,下列URL同样推荐观看:

  1. 可视化的 Fitts定律 http://particletree.com/features/visualizing-fittss-law/
  2. Fitts定律的在线Demo http://fww.few.vu.nl/hci/interactive/fitts/
  3. Fitts’ Laws以及其它定律的简介 http://www.sapdesignguild.org/community/design/print_laws.asp
  4. CodingHorror Blog中对Fitts定律的介绍文章(注意其示意图中有标注错误) http://www.codinghorror.com/blog/2006/08/fitts-law-and-infinite-width.html
  5. 2000年MSDN的文章,简单用Fitts Law分析了Web元素 http://msdn.microsoft.com/en-us/library/ms993291.aspx
  6. Pie Menu http://www.piemenus.com/
  7. Pie Menu开源实例 http://sourceforge.net/projects/circledock/
  8. QT的一个Pie Menu粗糙实现 http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Widgets/qtpiemenu/
  9. Pie Dock http://www.markusfisch.de/?PieDock
  10. JavaScript Pie Menu online demo http://www.markusfisch.de/downloads/PieDockDemo/ 源码在 http://www.markusfisch.de/downloads/PieDockDemo/PieMenu.js
  11. http://en.wikipedia.org/wiki/Marking_menu#External_links


扩展练习

  1. 分析Chrome浏览器在最大化状态下的标签页布局安排
  2. 寻找上文中没有提到的新视角,来比较Popup Menu和Pie Menu的优劣
  3. 用Fitts’ Law来分析鼠标手势的优劣
  4. 用Fitts’ Law来分析一个你认为设计得很好的网站,再分析一个你认为设计得很差的网站
  5. 这个平板杂志的概念设计中用到了Pie Menu,请分析它的优劣 http://berglondon.com/blog/2009/12/17/magplus/ (首页有视频和图像)
  6. 为这篇文章寻找理论基础 http://www.ifanr.com/3559 (《触不到的按钮》by ifanr 爱范儿 ♂专注于拇指设备的小众讨论)
  7. 用Fitts’ Law来分析Snap to Grid功能(或者allSnap小程序/winamp或gtalk等内建Snap功能的程序/Win7新增的窗口大小管理功能/Mac的窗口最合适尺寸功能/etc.)
  8. 用Fitts’ Law来分析Touch Pad和IBM小红点的优劣
  9. 分析这样的快捷键安排:Ctrl+X, Ctrl+C, Ctrl+V (为什么不用Ctrl+P来执行Paste?)
  10. 试着再举几个Fitts’ Law的应用实例(比如Anykey)
  11. 思考Fitts’ Law还有哪些不足/不适用的情形




Tagged with: , ,

神话

Posted in Uncategorized by Kenny Yuan on 2010/05/12
  1. HDD的C:盘比D:盘快
  2. LCD的黑屏和白屏几乎一样费电
  3. Cache大了不保证CPU更快
  4. CPU和compiler相互影响设计方案
  5. 32位机可以管理超过4G的地址(数据总线和地址总线是两回事儿)
  6. 虚拟机技术的流行是在个人电脑出现之前
  7. 低优先级process可以优先于高优先级process被OS调度运行
  8. 实时OS(或程序)不代表速度快
  9. srand()时用奇数效果更好
  10. main()函数不写return也会返回0
  11. C++中不存在所谓的“默认位拷贝copy ctor”或者“默认位拷贝assignment operator”
  12. LISP不是编程语言
  13. Fortran有好几十年都没有递归
  14. 最早的高级语言连if-else都没有
  15. Pascal是编译到字节码的(第一个推广使用字节码的)
  16. “内存分Stack, Heap和自由存储区”这种很多年前流行的说法有概念错误
  17. quick sort也可以是stable
  18. 有些Tree比Hash快
  19. “关系”是指笛卡尔积的子集
  20. NTFS其实也有链接
  21. 编译器每18年性能翻一翻
  22. 关于Windows/Mac/Linux的优缺点,有无数的谎言
  23. 电磁辐射是人类生存之根本
  24. 以上均为true

面试宝典2:算法和数据结构

Posted in Uncategorized by Kenny Yuan on 2010/05/07

本文已经404

原因——自己不满意,准备重写

Tagged with: ,

面试宝典1:程序性能优化

Posted in Uncategorized by Kenny Yuan on 2010/04/29

开场白:最近公司招人,接触了一批形形色色的工程师,但感觉绝大多数人基础都很差,在某次TL的讨论之后,就想到了写一个《面试宝典》系列。

卷首语:这个《面试宝典》名字是我一贯的标题党风格,其实在内容上都是很简单、很基础的——都是那种“不知道这些就别出来混”的知识点。所以,高手/牛人可以到此打住了——端咖啡——送客~~~

作/译序:此文可能会持续更新直到补充得比较完整为止,有什么要补充的欢迎留言

基础原则之万能利器:Profiling

如何测量距离?——直尺/游标卡尺/卷尺/etc
如何测量电压?——电压表/万用表
如何测量时间?——钟表/秒表
如何测量温度?——温度计
如何测量质量?——天平/台秤/etc
如何测量程序性能?——Profiler !

是的,Profiler就是这么一件又基础又重要的工具(小标题里的“万能”当然是标题党了,千万别真的相信)。要回答“程序为什么慢/什么地方慢/到底有多慢”等问题,离不开Profiler,就像测量长度离不开尺子一样。 (嗯,那位要测地月距离的,别抬杠了,请移步回你的实验室吧,我知道你是rocket scientist,高科技呢:)

可以使用软件Profiler,也可以使用硬件来做Profiling(DSO/Logic Analyzer/Hybrid DSO/Timer),在什么都没有的情况下,至少也可以输出Log或者用其它方式来达到Profiling的目的。
一般来说,测量工具对被测目标应该没有影响(或者极小),但是软件的Profiler却对被测目标有一定程度的影响——以此为代价,换来的是方便和廉价(免费)。

在系统外部对性能进行测试,也是一种测量性能的方式,只不过它所测量的粒度很大,不能用于分析源码,只能用于比较不同源码的优劣。

如何进行性能优化?

基本原则

原则:使用Profiler来找出最影响性能的那些程序,重点优化它们
分类:基本知识
提示:时刻记心间

原则:无论尝试了何种优化,都要使用profiler来测量这种优化
分类:基本知识
提示:时刻记心间

原则:一九原则
分类:基本知识
提示:运行中的软件有一种典型情况:10%的程序占了90%的运行时间,优化的重点是这10%的程序(10%和90%为约数)。应当使用Profiler来找出它们,改进它们并继续用Profiler测量改进的效果——在没有明显的性能热点的时候,就要考虑换一种思路进行优化了:比如使用“硬件优化”(参见下文)。在切换了设计和体系结构后,之前做的profiling也有可能会失效,要重新进行测量,每一种判断和决策必须得到证据的支持。

原则:Amdahl定律
分类:基本知识
提示:活学活用Amdahl思想(原本此定律是讲并行计算的)——在知道了“要优化的部分”占“整体”的比例之后,对于此次优化来说,最高可能的加速比也就可以计算出来了。所以不能过多期望,要多多开辟新战场。

原则:benchmark是个宝
分类:基本知识
提示:从来就没有可以代表所有程序的“典型程序”,所以要想在各种情况下均取得较好的性能,就需要使用benchmark方式对性能进行测量。

硬件优化

原则:使用更快的设备/通讯协议
分类:硬件优化
提示:有时候需要尝试跳出软件优化的框框来想问题
范例:使用SSD代替机械硬盘,在IO速率上你能提高2-5倍(在无RAID的情况下),在寻道时间上你能提高4个数量级(WOW!)

原则:对硬件友好
分类:硬件优化
范例:利用SIMD指令(如视频编码器);对Cache友好(数据Cache和指令Cache);对流水线友好(比如threaded code,削减分枝预测失误。注意这里的thread不是“线程”,是“线索化”);使用硬盘的外圈以达到更大的速度;

原则:利用硬件加速
分类:硬件优化
范例:使用D3D/OpenGL(哪怕是2D图形),使用GPU计算(如FFT),使用DMA不使用PIO,使用ASIC代替CPU进行专用计算(如常见的视频编解码专用芯片,还有加解密芯片),使用DSP对高负载数据进行处理(或预处理)

设计优化

原则:使用分布式计算
分类:设计优化
范例:使用HardoopHadoop;使用Memcached

原则:改进业务逻辑
分类:设计优化
范例:Google Chrome会扫描鼠标指针所在的位置,取得鼠标指针下的URL,然后去解析这些URL中的domain name(于是OS的DNS cache得到了warmup);对于某个name A,一组相关的names也会被送去解析(比如上次打开name A中的页面时,用到了其它的name B, C, D,那么这次也把name B, C, D送去解析)

原则:批量操作
分类:设计优化
备注:可以是业务逻辑优化,也可以去尝试利用底层提供的批操作机制(如writev)。批操作之后是否真的在性能上有提高,需要实测数据的支持。

原则:减少用户空间/内核空间的切换和数据交换
分类:设计优化
范例:例如在设计时就考虑去使用futex和zero-copy之类的技术,在特定场合下“有奇效”(嗯,前面这句话好有卖大力丸的感觉……)

原则:对输入进行缓存
分类:设计优化,缓存
范例:依靠CPU Cache/阵列Cache/磁盘Cache/磁盘/操作系统Cache/程序管理的Cache/专用Cache服务器等,对输入进行缓存,以加快速度

原则:对中间结果进行缓存
分类:设计优化,缓存
范例:预装载/索引/suffix tree

原则:对输出进行缓存
分类:设计优化,缓存
范例:使用buffer批量输出(匹配软件计算速度和设备的速度)

原则:空间换时间
分类:设计优化

原则:使用内存池
分类:设计优化,内存
提示:可以用类似slab的方式来优化可预期的内存使用

原则:使用更好/更合适的GC算法
分类:设计优化,内存

原则:控制内存交换
分类:设计优化,内存

原则:吸收掉不必要的界面更新
分类:设计优化,GUI

原则:只重绘更新的区域
分类:设计优化,GUI

原则:对可视化的结果进行缓存
分类:设计优化,GUI
备注:中间结果缓存的一个特例

原则:parallelism–利用多CPU/多核心
分类:设计优化,并行

原则:利用并发(concurrency)
分类:设计优化,并行
提示:在单CPU上跑并发也能提高性能
范例:线程池

原则:选取合适的锁类型
分类:设计优化,并行,锁
范例:使用Futex/读写锁/seq锁/RCU

原则:使用消息
分类:设计优化,并行,锁
备注:可以减少共享数据和锁

原则:使用异步模型
分类:设计优化,并行,锁
范例:使用epoll/kqueue等;nginx

原则:消除锁
分类:设计优化,并行,锁
提示:试用无锁的算法/数据结构(如Ring Buffer)/算法

原则:使用FP Paradigm
分类:设计优化,并行
提示:彪悍的FP不需要提示

算法优化

(其实算法往往是包含在设计中的)

原则:使用更优的算法,减小算法的阶
分类:算法优化
范例:使用BM/Sunday算法代替BF算法

原则:减小算法的常量(BigOO)
分类:算法优化
范例:使用sentry来编写double link list

原则:处理好Big Omega和BigO,使算法在“最坏的时候也不要太坏”
分类:算法优化
范例:quick sort,避免O(N*N)的情况

原则:使用更优的数据结构
分类:算法优化
范例:AVL Tree–>Hash Table–>Ternary Search Tree
备注:其实有些重复,主要是为了区分狭义的“算法”和“数据结构”

原则:寻找并行化算法
分类:算法优化
备注:和前面的parallelism有些重复,这个更多的是指可并行的算法而不是其它意义上的并行

小技巧

原则:编译器优化
分类:小技巧
范例:使用Intel的编译器,使用Intel的性能库IPP
备注:注意Proebsting定律

原则:树递归–>尾递归
分类:小技巧
备注:在许多语言中,尾递归是不需要栈的,自动转换成迭代了(例如在erlang中用尾递归实现无限循环)

原则:少用小技巧,以免妨碍大粒度上的性能优化
分类:小技巧
提示:主要是指那些影响并行计算的小技巧,或者那些没有使用profiler进行测量就草率进行的盲目优化

原则:远离“神话”
分类:小技巧
提示:有些流传的关于优化的神化不足信,“是骡子是马拉出来骝骝”,一切在profiler下见真章
范例:比如“大块内存分配非常慢”的神话(甚至有过一个人估计数量级的时候说:分配10M内存至少要1秒钟),比如“虚函数导致效率低”的神话,比如“解释运行比编译慢”的神话,等等

原则:使用Lazy Evaluation
分类:小技巧

原则:避免大对象复制
分类:小技巧
范例:RVO/RVal Ref

原则:预译码/编译成本地代码
分类:小技巧,解释器和VM
范例:PYC/HipHop

原则:混合使用各有优势的语言
分类:小技巧
范例:C里使用汇编;Python里使用C模块;

原则:使用二进制优化器
分类:小技巧
范例:JIT就是最出名的一种二进制优化;Win32SDK的BitBlt()函数也是;

……

重温:无论尝试了何种优化,都要使用profiler来测量这种优化
分类:红宝书
提示:时刻记心间

(2010年10月29日更新)

鸣谢:感谢Guancheng指出问题

参见:性能优化的方法和技巧(这是一个文章系列)

linuxperftools

图片来自http://www.brendangregg.com/linuxperf.html

Tagged with: ,

如何在午休时间写一个QT程序以便能够挣到同事的五毛

Posted in Uncategorized by Kenny Yuan on 2010/04/28
作者的话:本文有两个目的:1、Zhuangbility;2、教你如何变成五毛;3、展示QT的生产力。
译者的话:本文并非虚构,是真实发生过的——如有雷同你肯定认识我,欢迎到我座位这边来喝可乐(你一定知道这个典故的)

在30分钟内用QT写一个抓屏程序

(注:Qt这个词应该读成Cute,而不是Queue-Tee)


※ ※ ※ ※
叮咚、叮咚、叮咚——00:29:59
叮咚、叮咚、叮咚——00:29:58
叮咚、叮咚、叮咚——00:29:57
※ ※ ※ ※

此截图程序可以实现以下功能:

+跨平台运行
+可以截取全屏幕或者其中一部分
+鼠标选中的区域为高亮,未选中的区域亮度减半
+截屏后可以反复选择,直至满意为止
+保存文件到桌面并退出
+复制图像到剪切板并退出


※ ※ ※ ※
叮咚、叮咚、叮咚——00:25:59
叮咚、叮咚、叮咚——00:25:58
叮咚、叮咚、叮咚——00:25:57
※ ※ ※ ※

整个程序主要有三个关键点:(1)抓屏到内存;(2)随着鼠标选取,加亮显示内存中的图片;(3)将图片的一部分保存到剪切板或者文件。
在QT中,这三个问题很好解决,问题(1)可以直接调用QT函数:

    QPixmap px = QPixmap::grabWindow(QApplication::desktop()->winId())

※ ※ ※ ※
叮咚、叮咚、叮咚——00:24:59
叮咚、叮咚、叮咚——00:24:58
叮咚、叮咚、叮咚——00:24:57
※ ※ ※ ※

问题(2)也不难,只需要提前做一点点工作,在抓图后保存两个图片,一个是正常的,另一个是变暗之后的:


    screen_ = px.toImage();
将刚刚截屏得到的图像转换成设备无关的内存表示
    darkScreen_ = screen_;
在内存中对RGB减半处理,使图像变暗,先计算每行的字节数:
    int bytesPerLine = darkScreen_.width() * darkScreen_.depth() / 8;
然后处理每个行
    for ( int i = 0 ; i < darkScreen_.height() ; ++ i )
    {
        uchar* lineBuf = darkScreen_.scanLine(i);
scanLine函数可以取得指定行的起始指针,不必再自己计算了。取得行指针后对每像素RGB值进行操作
        for ( int x = 0 ; x < bytesPerLine ; ++ x )
            lineBuf[x] /= 2;
    }

在这里没有尝试加速图片变暗的过程,效率问题最后再综合考虑。

※ ※ ※ ※
叮咚、叮咚、叮咚——00:22:59
叮咚、叮咚、叮咚——00:22:58
叮咚、叮咚、叮咚——00:22:57
※ ※ ※ ※

有了这两张图片,就可以进行绘图了:

void Widget::paintEvent(QPaintEvent *)
{
声明绘图对象,目标为窗口
    QPainter painter(this);
全屏绘制暗图像:
    painter.drawImage(0, 0, darkScreen_);
在选定的区域绘制亮图像:
    painter.drawImage(currentRect_, screen_, currentRect_, Qt::AutoColor);
}

currentRect_是在鼠标事件中保存的当前选择区域,它的计算也很简单,在鼠标的移动消息处理器中:


void Widget::mouseMoveEvent(QMouseEvent * e)
{
    if ( dragging_ )
        end_ = e->globalPos();
保存旧区域,用于后面的区域合并
    QRect oldRect = currentRect_;
设置新区域
    currentRect_.setTopLeft(start_);
    currentRect_.setBottomRight(end_);
调用normalized函数解决负宽度或者负高度问题
    currentRect_ = currentRect_.normalized();
QRect::united()函数用来求两个rect合并后的rect,可以省去许多手工计算。
且QT的repaint()函数也不需要关心背景擦除问题,QT4以上都是自动double buffer
    repaint(oldRect.united(currentRect_));
}

至此,问题(2)处理完毕。


※ ※ ※ ※
叮咚、叮咚、叮咚——00:18:59
叮咚、叮咚、叮咚——00:18:58
叮咚、叮咚、叮咚——00:18:57
※ ※ ※ ※

为处理问题(3),需要得到指定图像的指定区域,并且一个图像对象来表示。将这个功能编写成以下辅助函数:


static QImage clipImage(const QImage& srcImage, QRect rect)
{
    QImage image(rect.size(), QImage::Format_RGB32);
    const QImage* target = &srcImage;
    QImage targetImg;
    if ( srcImage.depth() != 32 )
    {
        targetImg = srcImage.convertToFormat(QImage::Format_RGB32);
        target = &targetImg;
    }
    int bytesPerPixel = image.depth() / 8;
    for ( int i = 0 ; i < image.height() ; ++ i )
    {
        uchar * line = image.scanLine(i);
        const uchar * srcLine = target->scanLine(rect.top() + i);
        memcpy(line,
               srcLine + rect.left() * bytesPerPixel,
               rect.width() * bytesPerPixel);
    }
    return image;
}

这个函数有点长,但思路却很简单:
1、先创建一个小图像,宽高与选区相同
2、取得源图像的数据,复制到小图像中
3、返回小图像

有了这个辅助函数之后,想保存文件,就可以这样写:


QImage img(clipImage(screen_, currentRect_));
img.save(pathName, "png");
想把图片放到剪切板的话,可以这样写:

QApplication::clipboard()->clear();
QApplication::clipboard()->setImage(clipImage(screen_, currentRect_), QClipboard::Clipboard);
QImage(QApplication::clipboard()->image(QClipboard::Clipboard)); // Retrieve data from clipboard to make it owns the data

※ ※ ※ ※
叮咚、叮咚、叮咚——00:10:59
叮咚、叮咚、叮咚——00:10:58
叮咚、叮咚、叮咚——00:10:57
※ ※ ※ ※

再往下就是处理一些鼠标和键盘事件,比如在双击时复制到剪切板并退出,在按Ctrl+S时保存到文件并退出,按ESC时直接退出,等等

最终完成,编译,修改typo并运行,发现速度还可以,故取消profiling和性能调优计划,直接和DLL一起打包。至此任务完成,领取五毛工资。


※ ※ ※ ※
叮咚、叮咚、叮咚——00:00:09
叮咚、叮咚、叮咚——00:00:08
叮咚、叮咚、叮咚——00:00:07
叮咚、叮咚、叮咚
叮咚、叮咚、叮咚——00:00:05
叮咚、叮咚、叮咚
叮咚、叮咚、叮咚——00:00:03
叮咚、叮咚、叮咚——00:00:02
叮咚、叮咚、叮咚——00:00:01
叮咚、叮咚、叮咚——00:00:00

(EOF)
Tagged with: , ,

史上最全的英语连读规则一网打尽

Posted in Uncategorized by Kenny Yuan on 2009/09/02

你会正确地读以下单词么:feel, fool, heal, wheel, …

你会正确地读以下词组么:I am, s/he is, I always, too often, …

如果你不会正确发音,那么你需要学习连读规则;如果你能够正确发音,但不知道原因,那你更需要学习连读规则——

今天,我就模仿赵老湿,来讲一讲英语口语中的连读。
“连读”在英语中叫Word Connections,借用法语的词汇时叫Liaison,读音为[li’eizn]——在这里要多说一句:从法语中借来的词读音一般都比较怪,一定要先查字典再去读它,免得搞错,比如debut[‘deibju:]

连读的意义

连读是语调中非常重要的一个组成要素。而语调是让别人更好听懂、更好理解的重要途径——语调的正确,比发音的准确还要重要。因为语调涉及的内容太多,而且很难用文字来描述,所以在这里只讲连读。
可能有人会认为连读会造成别人的理解困难,他们认为:还是把单词一个挨一个地读清楚更容易听明白。虽然这种说法明显是错误的,但是在这里我也不想浪费文字去反驳,读者们请自行决定是否要阅读或者离开。

一个例子

这里是一个连读的例子。在这个例子里,不仅仅有连读的存在,还包含发音的一些变化,请仔细分辨:
书写英语:They tell me that I’m easier to understand.

口语连读:theytellme thedaimeasier der-undersdand

连读的分类

英语中的连读主要有四种:
1)辅音+元音的连读(Consonant + Vowel)
2)辅音+辅音的连读
3)元音+元音的连读
4)T, D, S 或 Z + Y的连读

1. 辅音+元音的连读

一般来说中国人比较熟悉这种连读——前一个词由辅音结尾,后一个词由元音开头,于是就很自然地连起来了,比如:

My name is… [my nay•miz]
because I’ve. [b’k’zäiv]
pick up on the American intonation… [pi•kə pan the(y) əmer’kə ninətənashən]

不只是句子中,读字母缩写也可以连读:

LA [eh•Lay]

读数字时也可以连读:

902 5050 [nai•no•too fai•vo•fai•vo]

再来几个简单例子:

hold on [hol don]
turn over [tur nover]
tell her I miss her [teller I misser]

因为这种连读一般初中生都会,在这里就不详细介绍了,重头戏在后面,马上开演。

2. 辅音+辅音的连读

这个很难用文字描述,放到最后再讲。

3. 元音+元音的连读

如果前一个词是由元音[u]结尾,下一个词由元音开头,那么,在[u]后面加上一个辅音[w]
如果前一个词是由元音[i]结尾,下一个词由元音开头,那么,在[i]后面加上一个辅音[y]

只说规则似乎有点不好理解,看例子就明白了。

Go away. [Go(w)away]

在电影Big Fish中,巨人Carl说过这句话。因为巨人说话又慢又重,所以那个w很明显。
再来看一个例子:

I also need the other one. [I(y)also need thee(y)other one]

这种连读不能把辅音w或者j发得太重,否则会显得很傻,但是不发这两个辅音的话又会很难念得顺口。

go anywhere [go(w)anywhere]
so honest [so(w)honest]
through our [through(w)our]
you are [you(w)are]
he is [he(y)is]
do I? [do(w)I?]
I asked [I(y)asked]
to open [to(w)open]
she always [she(y)always]
too often [too(w)often]

4. T, D, S 或 Z + Y的连读

如果前面的单词是以T/D/S/Z结尾,后面的单词是以Y开头(一般是you这个词),那么有如下的连读规则可以使用。

4.1. T + Y = CH

What’s your name? [wəcher name]
Can’t you do it? [kænt chew do(w)it]
Actually [æk·chully]
Don’t you like it? [dont chew lye kit]
Wouldn’t you? [wooden chew]
Haven’t you? [hæven chew]
No, not yet. [nou, nä chet]
I’ll let you know. [I’ll letcha know]
Can I get you a drink? [k’näi getchewə drink]
We thought you weren’t coming. [we thä chew wrnt kəming]
I’ll bet you ten bucks he forgot. [æl betcha ten buxee frgät]
Is that your final answer? [is thæchr fin’læn sr]
natural [næchrəl]
perpetual [perpechə(w)əl]
virtual [vrchə(w)əl]

4.2. D + Y = J

Did you see it? [didjə see(y)it]
How did you like it? [hæo•jə lye kit]
Could you tell? [küjə tell]
Where did you send your check? [wεrjə senjer check]
What did your family think? [wəjer fæmlee think]
Did you find your keys? [didjə fine jer keez]
We followed your instructions. [we fallow jerin strəctionz]
Congratulations! [k’ngræj’lationz]
education [edjə·cation]
individual [indəvijə(w)əl]
graduation [græjə(w)ation]
gradual [græjə(w)əl]

4.3. S + Y = SH

Yes, you are. [yeshu are]
Insurance [inshurance]
Bless you! [blesshue]
Press your hands together. [pressure hanz d’gethr]
Can you dress yourself? [c ‘new dreshier self]
You can pass your exams this year. [yuk’n pæsher egzæmz thisheer]
I’ll try to guess your age. [æl trydə geshierage]
Let him gas your car for you. [leddim gæshier cär fr you]

4.4. Z + Y = ZH

How’s your family? [hæozhier fæmlee]
How was your trip? [hæo·wəzhier trip]
Who’s your friend? [hoozhier frend]
Where’s your mom? [wεrzh’r mäm]
When’s your birthday? [wεnzh’r brthday]
She says you’re OK. [she sεzhierou kay]
Who does your hair? [hoo dəzhier hεr]
casual [kæ·zhyə(w)əl]
visual [vi·zhyə(w)əl]
usual [yu•zhyə(w)əl]
version [vrzh’n]
vision [vizh’n]

附录: 音节省略和连读放在一起

I have got to go. I’ve gotta go.
I have got a book. I’ve gotta book.
Do you want to dance? Wanna dance?
Do you want a banana? Wanna banana?
Let me in. Lemme in.
Let me go. Lemme go.
I’ll let you know. I’ll letcha know.
Did you do it? Dija do it?
Not yet. Nä chet.
I’ll meet you later. I’ll meechu layder.
What do you think? Whaddyu think?
What did you do with it? Whajoo do with it?
How did you like it? Howja like it?
When did you get it? When ju geddit?
Why did you take it? Whyju tay kit?
Why don’t you try it? Why don chu try it?
What are you waiting for? Whaddya waitin’ for?
What are you doing? Whatcha doin’?
How is it going? Howzit going?
Where’s the what-you-may-call-it? Where’s the whatchamacallit?
Where’s what-is-his-name? Where’s whatsizname?
How about it? How ’bout it?
He has got to hurry because he is late. He’s gotta hurry ‘cuz he’s late.
I could’ve been a contender. I coulda bina contender.
Could you speed it up, please? Couldjoo spee di dup, pleez?
Would you mind if I tried it? Would joo mindifai try dit?
Aren’t you Bob Barker? Arnchoo Bab Barker?
Can’t you see it my way for a change? Kænchoo see it my way for achange?
Don’t you get it? Doancha geddit?
I should have told you. I shoulda toljoo.
Tell her (that) I miss her. Teller I misser.
Tell him (that) I miss him. Tellim I missim.
Did you eat? Jeet?
No, did you? No, joo?
Why don’t you get a job? Whyncha getta job?
I don’t know, it’s too hard. I dunno, stoo härd.
Could we go? Kwee gou?
Let’s go! Sko!

最后的话

可能有人会觉得奇怪,为什么在附录之后还有一段。嗯,就像电影 在字幕结束后的隐藏镜头一样,这一段是要用来揭密的:本文中的所有内容,包括规则和例子,都来自于ATT——《American Accent Training》这本书,Amazon上的网址是:http://www.amazon.com/American-Accent-Training- Speaking-Pronouncing/dp/0764114298/ref=sr_1_2?ie=UTF8&s=books& qid=1251888224&sr=8-2。故而,所有的荣光属于原作者Ann Cook女士。另外,关于辅音和辅音的连读,恕我不能用简短的文字描述清楚,请自行参考原书。谢谢观赏,再见……

Tagged with: ,