posts - 28, comments - 27, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2006年9月18日

再也无法忍受无法在Firefox下面写blog的痛苦,再加上这里缓慢的网速~~~于是决定~~搬家

新家地址:dearwolf.javaeye.com

posted @ 2007-01-08 10:07 小小凉粉 阅读(330) | 评论 (2)编辑 收藏

默认情况下,SWT的Table只会给整个Table设置Tooltip,要对每一个TableItem设置Tooltip的话,就要监听鼠标事件了:


        table.addMouseTrackListener(
new MouseTrackAdapter() {
            
public void mouseHover(MouseEvent event) {
                Point pt 
= new Point(event.x, event.y);
                
int index = table.getTopIndex();
                
while (index < table.getItemCount()) {
                    TableItem item 
= table.getItem(index);
                    
for (int i = 0; i < table.getColumnCount(); i++) {
                        Rectangle rect 
= item.getBounds(i);
                        
if (rect.contains(pt)) {
                            Object object
= item.getData();
                            ........
                        }
                    }
                    index
++;
                }
            }
        });

在省略号的地方就可以对对象进行转型了

posted @ 2006-12-11 19:13 小小凉粉 阅读(1946) | 评论 (4)编辑 收藏

1、有人竟敢叫嚣要“屠龙”

上海某高校吴友富同志说:因为“龙”的英文“Dragon”,在西方世界被认为是一种充满霸气和攻击性的庞然大物。“龙”的形象往往让对中国历史和文化了解甚少的外国人由此片面而武断地产生一些不符合实际的联想,故提出龙可能不再适合代表中国。

解读:中 国,一个有着上下几千年文化历史的国家,一个有着13亿人口的大国,一个曾经以小米加步枪硬是赶跑了持着洋枪洋炮的侵略者的民族,一个英雄辈出的国家,为 什么连我们世代所敬仰的代表我中华儿女的标志也要问问外国人是否合适?如果哪天他们说我们的国旗、国歌他们不喜欢,我们也要更改吗?

所以我说了,以后爸爸也该叫爹地了。今后大伙儿也别过春节了,一起过圣诞去;除夕也不要了,改在12月24日,叫平安夜。为啥?老外不喜欢!

2、李银河:换妻是公民合法权利

丧夫性学家李银河:“换妻是公民合法权利。一切东西都应该要丰富多彩。如果家庭都只是一夫一妻这个模式,反而显得过于单调”
  
解读:这话跟前些年“自愿的奴役是一种自由”这样一个伪命题一样不需要废话。自愿为奴隶当然是一种自由,但是它违背了自由这样一个大前提。换妻当然也是一种合法权利,但是它违背了一夫一妻制和《婚姻法》这个大前提。

解读:不过不知道李银河愿不愿自己试一把。没丈夫跟人换可以玩3P嘛


3、自称白居易后人的国学辣妹白鹿鸣

“我最擅长勾引人,孔子也不例外。我的一夜情值10万,不过孔子说食色性也,我去慰他籍千年的寂寞,他也一定是很高兴的。”

解读: 不知道白居易知道有这样的后人会不会气的从棺材里爬出来。想出名,不是坏事。但是甩个大脸沾着祖宗的光还说勾引谁谁谁这样的话就有点让人倒胃口了。

4、饶颖性爱日记

饶大妈数年如一日地死缠猛打央视拨阴员赵老湿,起因据说是赵老湿舍不得给饶颖3800块钱,哎,何必呢?早知道今天这个场面,估计后面加上三个0,赵老湿也认了。
  
饶 颖日记(三)节选:有几次在一起,他用刀割我的手臂,用针沾了他的唾沫扎我的阴部,说是消毒。我痛得喊叫,他却兴奋不已地说:“宝贝,你不知道这样做,我 有多快乐,让我扎扎吧。”“赵忠祥虐待成性,即使我在经期,他也要与我发生关系。我不愿意,他就骂我打我,迫使我屈服。2000年上半年,我的泌尿系统因 此受感染,治疗不及时,导致肾炎。”
  
解读:“宝贝,你不知道这样做,我有多快乐,让我扎扎吧。” 这哪是赵老湿,明明就是《依波拉病毒》和《人肉叉烧包》里的 黄秋生嘛!

5、巨NB的老师

一个女孩和同学开玩笑,把对方的衣服脱光了,后来被班主任知道了,他叫来了三方的家长。当家长们决定不予以追究,只要对方道歉的时候,他说了:“呀,这可不得了,以前听说也有过这样一个例子,一个人把一个女同学的衣服脱光了,最后判了16年呢”最后那个女孩子因害怕自杀。

解读:终于体会到了什么叫做唯恐天下不乱?既然受害方都表示不愿再追究,为什么你要那么危言耸听呢?传说中的皇帝不急,你个太监急个球啊?最后结果是:一朵鲜花又凋谢了!

6、医托说:揍的就是院长!

2006年11月23日,复旦大学附属眼耳喉鼻医院院长助理、浦东分 院院长:张天宇在揭穿医托的把戏后,遭到了一群医托群殴。此 时张院长大呼:我是医院院长!为首的一个医托答曰:揍的就是 院长!

解读:以前在我们眼里,医托都是偷偷摸摸的,像做贼一样(本来就是做贼),现在你看看,时代进步了,社会发展了,医托也翻身得解放了,还能说出那样天地惊,鬼神泣的话!可以肯定是医托史上最NB的。

7、苏丹红鸭蛋吃不死人,放心吧

北京市食品办专家:“按每个鸭蛋约60克进行折算,体重60公斤的成人每天食用1200多个“涉红鸭蛋”,才有可能达到诱发动物肿瘤的剂量。”

解读:食 品办专家原来一直在以人的体重与有毒食物食用量之比,作为他们工作的指导思想。你吃了毒木耳吗?专家可以告诉你:按多少多少克进行折算,体重60公斤的成 年人每天食用1吨,“才有可能达到诱发动物肿瘤”。你吃了毒猪肉吗?你吃了毒韭菜吗?你吃了毒大米吗?你吃了含有苏丹红Ⅰ号的广东亨氏美味源辣椒酱、肯德 基新奥尔良烤翅吗?吃吧,放心地吃吧,死不了。

8、北大教授阿忆:“在北大月收入4786元,靠学校那点工资很难生存和安心教学。”

解读:幸亏阿忆教授还有几个兼差,要不怎么能在“哭穷”之际,又在中关村附近新购置了一套豪宅,“300万差1万”。

9、教育好比逛市场?

教育部新闻发言人王旭明:“教育就好比逛市场买东西,如果有钱,可以去买1万元一套的衣服;如果没钱,就只能去小店,买100元一套的衣服穿。”

解读:许多国家的教育部门,都鼓励年轻人勇于追逐自己的梦想,鼓励年轻人突破自我,进入更高的层次、更好的学校深造,不想当将军的士兵不是好士兵,不想上哈佛的学生不是好学生。可我们的教育部门竟然对年轻人说:要考虑自己的经济能力,要有自知之明……

10、社会学家郑也夫:“自来水100元一吨保证可持续洗澡”。

解读:郑 老师说得很有道理,他算了账:瓶装矿泉水每瓶500—600毫升,1.5元一瓶。一吨瓶装矿泉水3000元。罐装饮用水一罐19升,大约10元多一罐。一 吨罐装饮用水550元。一吨自来水100元离谱吗?商人忽悠您买罐装水可以,自来水提价就不行?即使按照这个价格算,吃三根冰棍的价格(3元钱),就能淋 浴一次(淋浴龙头开4分钟大约用水30升)。为什么淋一次浴就一定要比吃三根冰棍便宜?

posted @ 2006-12-06 20:31 小小凉粉 阅读(283) | 评论 (0)编辑 收藏

从灰姑娘变成公主,和生下来就是公主,毕竟不一样,前者不会有后者的单纯,但也不会像后者那样容易受伤。

 

见到张靓颖的那刻,屋子里人非常多,她一个箭步冲向沙发,一把将头顶上的报童帽丢到桌子上,叽里呱啦地和公司相熟的同事攀谈起来,语速快得惊人,,像个孩子般手舞足蹈。其间,还以非同寻常的速度干掉了一整瓶鲜橙多。

 

经同事提醒,她才发现了我,于是规规矩矩坐过来,重新将双手缩到长袖衣服的袖管中,语速变得缓慢,神情收敛,一下子就变成另外一个样子。

 

在厦门某酒吧举行的“凉粉”与张靓颖的见面会上,“凉粉”手牵手,用人墙把所有记者都隔离起来,不让记者靠近张靓颖,他们警告媒体记者,不要影响到他们的 “公主”。紧接着,在厦门国际马拉松发令式的媒体见面会上,张靓颖到场,同时到场的还有大批“凉粉”,其中一位义正词严“警告”记者说:“不要问八卦问题,我们已经不是传统意义上的粉丝,靓颖也不是传统意义上的明星。”

 

在这次采访前,到百度张靓颖吧上收集问题,也收到了同样的警告——“她已经把最美的歌声给了我们,站在这个舞台上忍受了很多伤害,所以,我们把生活还给她。郑重对你说,如果你是善良的,请不要问她私生活。她的性格很倔,如果你问了,而她的态度不好,我们只会鼓掌支持她。”

 

FANS 对张靓颖的维护已经到了无以复加的地步,尽管许多人认为,不少凉粉属于中产精英男士,他们大多低调——但低调不代表无声,连张靓颖都说,“现在‘玉米’和‘盒饭’更疯狂?我没有觉得啊 ! 我的粉丝也很热情” FANS 爱上的是和他们某些地方很相似的张靓颖,虽然看起来平平静静,但遇弱则柔,遇强则刚。就像前不久,她“斗胆”以一个刚出茅庐的歌手身份将上海某著名媒体一纸诉状告上法庭,理由是她认为该媒体侵害了她的名誉权。

 

事实上,早在去年超女比赛中,她的“战斗”就开始了。在那样一个比赛中,嗓音一流的张靓颖遭遇到一种她从未经历过的尴尬,那就是:她唱得再好,也得不到冠军。虽然我们得不到证实,但她一定心里明白,这就是所谓的游戏规则。她的失落逐步变成了“孤傲”,被称为“自信得无可救药”,评委旁敲侧击,暗示她心机过重,甚至故意避而不谈她的演唱实力。而这个早早就经历过风浪的女孩,也从怯怯接受变为有意还击。比如,其中一场比赛中她唱完后,评委轮番向她发问:“你有没有感冒?发烧?生病?状态不佳?”张靓颖响亮回应:“我没有生病,我的状态非常好。”

 

正是这种直接,使得喜欢与不喜欢她的人截然分派。

 

爱她的叫她公主。

 

不与媒体为敌,她是个天生的艺人,懂得圆熟地闪避危险。

 

网上有个流传颇广的帖子《不穿水晶鞋也能成为公主》中写到过一段她幼年时的经历,大概意思是小学时候她参演童话剧《灰姑娘》,剧情需要她试穿水晶鞋,她却擅自改了台词,高喊着“谢谢你,我不穿 ! ”使童话剧草草收场,当我问道她这个情节时,她却一脸茫然:“没有吧,我怎么不记得我这样干过。”紧接着她又打圆场说,“你知道嘛,许多 FANS 喜欢凭着美好的想象编故事,让我在其中变得很美,事实上,我可没有那么大胆 ! 小时候一直惟‘母命’是从,不敢吭气,做错了事,妈妈是真会下狠手教训我的 !

 

很乖,懂事,很早就学会坚强,还是也难捱娱乐圈的残酷,她在博客上写:“进入娱乐圈前,许多人提醒我要提防不良娱记……进入娱乐圈几个月,我已经见识了他们的高深道行,他们可不是落井下石,而是路上挖井,再用无敌幻化绯闻掌将你打入地狱……”几次公开落泪,却为她赢得更多感动,从不适应到接受、消化和享受成名带来的乐趣,她变得越来越从容。毕竟,从灰姑娘变成公主,和生下来就是公主的人木不一样的,前者不会有后者的单纯,但也不会像后者那样容易受伤。

 

事实上,张靓颖并不是一个与媒体为敌的人,她是一个天生的艺人,懂得圆熟地闪避危险发挥长项,有人说她单纯,的确有些牵强。采访中,在很多问题上,她都表现出了相当成熟的特质。比如,官司到现在尚未水落石出,提及此事她淡淡地说:“我已经把所有事都交给公司去做了,自己现在只是专心致志录专辑。”比如,当被问到参加超女比赛成功除了实力和人气以外还有什么其它因素时,她哈哈大笑:“当然是运气了 ! ”而被追问平凡人如何才能有“好运气”,是否有“潜规则”才在时,她眼珠一转,很无辜:“我怎么知道,运气啦,神鬼莫测的,谁能清楚它的走向呢?”问她,什么事会引起她的不快,她很斩钉截铁地说:“嗯,如果你不按照我今天说的来写,我就会不开心。”

 

其实,她在采访中所表现出的敏捷、大方,虽心存抗拒和抵触却几乎不露痕迹,比起在娱乐圈摸爬滚打多年的艺人甚至是一线大牌来,都要漂亮和得体的多。

 

关于新专辑, FANS 有个很大的呼声,那就是——强烈需要口水歌,她拖长了声回答:“有,让他们放心,一定有 ! ”可紧接着问她什么是口水歌时,她突然摇头,“不知道,因为说不好,一个人一个定义吧。比如某首歌,有人觉得是口水歌,别人也许不这么认为,觉得很有内涵啊。”

 

“不知道 + 因为…… ( 一长串的解释 ) ”一定程度上成了她回答问题的模式,她在这个过程中,尽量寻找两全其美的答案。 FANS 不择生熟的狂热拥趸 VS 希望她至少有一首“口水歌”,原本就是一个矛盾,应该如何选择自己的定位?张靓颖想了想,依旧是:“不知道,但我在很用心地唱歌,很努力地为大家呈现一个多元华的自己。”

 

于是新专辑出现了一个很有趣的现象:英文歌和中文歌并存,欢快的舞曲和忧伤的抒情并存,翻唱与原唱并存,炫耀声线的阳春白雪和琅琅上口的下里巴人并存。

 

厌她的人吹毛求疵。

 

身陷娱乐圈,就免不了被折腾,她知道在恰当时候自娱娱人。

 

现在在成都,只要对出租车司机说“去张靓颖唱歌的酒吧”,司机就能径直把你拉到玉林生活广场,那里的音乐房子和空瓶子都是她唱过歌的酒吧。但是成名带给她的不只是“成名”,一路 PK 摆脱了平民身份的张靓颖不知怎么的,她的名字就和一些男女有了瓜葛,先是一位自称好友的人大曝张靓颖以前的情史,还言之凿凿地称她曾为某 男友自杀,后有与某教授关系暧昧;不久后,

张靓颖又成了黄健翔离婚的直接“杀手”,接下来再是访谈中谈到欣赏姚明便被传为“想借大个子炒作”,然后是刘翔驳了她的面子没能参加她亲手送上票的演唱会,有人跳出来说:“张靓颖,请别坑害刘翔 ! ”再到后来,又有所谓她曾经的“闺中密友”出来编排她翻脸不认人的不是……闹到眼前,以身兼在校自考生和当红歌星两重身份参加四川大学 110 年校庆的张靓颖,依旧被指指点点,理由就是,她是自考生,能算校友吗?一批网友忿忿然:张靓颖何德何能参加校庆?学校不以学术成就宣传自己,却让一个不合格的逃学艺人为自己贴金,可耻呀可耻 !

 

被放在更大的舞台上,需要的是歌唱以外的实力。

 

面对纷扰,张靓颖只是淡淡地说:“我几乎不上网看这些,每天回家很晚,电视也懒得看,从美国带回来的那些 CD 都没来得及仔细听,现在每一天雷打不动,就剩下洗澡,打开计算机连连看,等头发干,然后睡觉。”

 

而半年前,当记者提及争议和绯闻时她说:“娱乐圈都是这样,圈子里没有谁能逃过这些,这个怎么说呢,也算是一种规矩了。”从哭泣、气愤,到拾了隐身草,闭眼不理麻烦事,张靓颖已经学会为自己排解烦恼。

 

不过有一件事她倒是很豁达,那就是一直被攻击的造型问题。讨厌她的人特别喜欢揪住“不会打扮”这一点不放,而她自己这次却也从了众:“穿衣服这件事,我真是搞不懂,我就喜欢穿的特随便,而且又倔又懒。每次出席什么场合,都应该是带几身衣服让造型师挑选,而我经常就带一身,让他们没的挑。公司 12 岁生日那天,我本来没穿那条隆重的黑裙子,只是白衬衫牛仔裤过来了,到场便傻眼了,因为在场的工作人员工作服就是白衬衫牛仔裤。还有去年超女比赛时有一套衣服,一开始我死活不想穿,和造型师打了半天架,最后拗不过只能穿了,结果到现在都被大家说那时最漂亮的一身,你说我审美是不是有问题啊?”

 

走红,自然会有负面新闻不断找上来。“我忘性很大,基本上属于杂草型,哭完就没事了。”张靓颖的智慧之处在于,她懂得在恰当的时候自娱娱人。娱乐圈就是名利场,明星就是金鱼,老百姓是看客。谁要是嫌看热闹还不够过瘾,自己跳进水里一起扑腾,那就真是典型的“无极”了,对于“无极”之人,她最终选择了不予理会。

posted @ 2006-11-16 12:07 小小凉粉 阅读(280) | 评论 (0)编辑 收藏

目的1:打开一个新的对话框时,如何设定它和父对话框的相对位置?比如在登录对话框有一个“创建新帐号”的按钮,用户点击以后,就出现新的对话框用于注册,请问如何能让新的对话框和旧对话框排列的整齐一些?应该是能设定二者的相对位置吧?

最开始,以为要用Shell.setLocation来设置,但是对于一个Dialog而言,它的Shell在什么时候才能初始化呢?

我 在构造函数里面,configureShell(Shell newShell)方法里面,Control createDialogArea(Composite parent)方法里面都调用过了this.getShell方法想得到当前的Shell,结果都抛出空指针异常....

后来看书发现,应该重写protected Point getInitialLocation(Point initialSize)方法

比如,在最开始的例子中,在第二个对话框中我重写了该方法,代码如下:

protected Point getInitialLocation(Point initialSize) {
        Point location 
= new Point(this.getParentShell().getLocation().x
                
+ this.getParentShell().getBounds().width, this
                .getParentShell().getLocation().y
                
+ this.getParentShell().getBounds().height
                
- this.getInitialSize().y);
        
return location;
    }


其结果就是两个对话框底部对齐的平行排列:)

目的2: 登陆对话框要记住上次的位置。

想了半天,好像只能用IPreferenceStore来做了,在继承了AbstractUIPlugin的类中放入两个常量:

    public static final String LOGINDIALOG_POSITION_X = "LOGINDIALOG_POSITION_X";

    
public static final String LOGINDIALOG_POSITION_Y = "LOGINDIALOG_POSITION_Y";

然后重写两个方法:

    @Override
    
protected Point getInitialLocation(Point initialSize) {

        String xposition 
= preferenceStore
                .getString(Peer68TPlugin.LOGINDIALOG_POSITION_X);
        String yposition 
= preferenceStore
                .getString(Peer68TPlugin.LOGINDIALOG_POSITION_Y);
        
if (xposition == null || yposition == null || xposition == ""
                || yposition == ""
) {
            
return super.getInitialLocation(initialSize);
        } 
else {
            
return new Point(Integer.parseInt(xposition), Integer
                    .parseInt(yposition));
        }
    }

    @Override
    
public boolean close() {
        preferenceStore.setValue(Peer68TPlugin.LOGINDIALOG_POSITION_X, 
this
                .getShell().getLocation().x);
        preferenceStore.setValue(Peer68TPlugin.LOGINDIALOG_POSITION_Y, 
this
                .getShell().getLocation().y);
        
return super.close();
    }

大功告成!

posted @ 2006-11-08 15:23 小小凉粉 阅读(2193) | 评论 (0)编辑 收藏

1. The Maven Command:

mvn archetype:create
-DarchetypeGroupId=org.springframework.osgi
-DarchetypeArtifactId=spring-osgi-bundle-archetype
-DarchetypeVersion=1.0-SNAPSHOT
-DremoteRepositories=http://static.springframework.org/maven2-snapshots
-DgroupId=maventest
-DartifactId=maventest
-Dversion=1.0.0


2. After the project is successfully created, please add the following repositories to the POM


 
<repository>
   
<id> springframework.org </id>
   
<name>Springframework Maven SNAPSHOT Repository</name>
   
<url> http://static.springframework.org/maven2-snapshots/ </url>
 </repository>                 
                       
 
<repository>                                        
   
<id>safehaus-repository</id>                       
   
<name>Safehaus Repository</name>                   
   
<url>http://m2.safehaus.org </url>                  
 </repository> 

3. run "mvn compile", everything is ok! :-)

Thanks for the help of every guys。

posted @ 2006-10-31 21:41 小小凉粉 阅读(1640) | 评论 (0)编辑 收藏

				

posted @ 2006-10-30 11:58 小小凉粉 阅读(252) | 评论 (0)编辑 收藏

第一个评价是来自于我前年冬天的博客,第二个评价是来自于我01年的一篇文章----差别还可以.....

小小凉粉,您的总体评价:

文字的平民化韵味浓郁,具有很强的生活气息;相对正统的创作路线,可读性较强。架构清晰,逻辑性强,情节缜密,可读性强;文章内容丰富,观点翔实可圈可点;在用词范围方面可以着重下功夫改进。情节缜密题材的小说值得尝试,将推理、悬念、历史的因素掺杂其中;同时也可以尝试杂文、评论等文体。行文时留心描写与情节结构的紧密配合,必然会诞生令人耳目一新的作品。


小小凉粉,您的测算结果:

通过测算,您的文章与知名作家的相似度比较结果见下:

王安忆
27%
没有想到吧,你有这位作家那么一点点的味道哟。
张小娴
25%
没有想到吧,你有这位作家那么一点点的味道哟。
郑渊洁
11%
如果不是我们科学的分析结果,你没有发觉自己还有些许这位作家的风格吧^_^

小小凉粉,您的总体评价:

古风古韵的味道,古色古香的文字。架构清晰,逻辑性强,情节缜密,可读性强;文章内容丰富,观点翔实可圈可点;在用词范围方面可以着重下功夫改进。情节缜密题材的小说值得尝试,将推理、悬念、历史的因素掺杂其中;同时也可以尝试杂文、评论等文体。行文时留心描写与情节结构的紧密配合,必然会诞生令人耳目一新的作品。


小小凉粉,您的测算结果:

通过测算,您的文章与知名作家的相似度比较结果见下:

古龙
17%
这个区间是比较正常的,看来你已经有了掌握神韵的感觉喔。
张小娴
13%
如果不是我们科学的分析结果,你没有发觉自己还有些许这位作家的风格吧^_^
钱钟书
8%
如果不是我们科学的分析结果,你没有发觉自己还有些许这位作家的风格吧^_^

posted @ 2006-10-26 18:10 小小凉粉 阅读(287) | 评论 (0)编辑 收藏

Sailor   骂的,真骚,用英语聊个P啊
小刀   是啊
小刀   你真骚 
Sailor  你更骚
Sailor  你最骚
小刀   你最骚
小刀   你是骚上加骚
Sailor  骚!
小刀   别忘了,是你先说英语的!
Sailor  谁让你跟着说来着
小刀   所以最骚的是你
Sailor  你是跟骚!
小刀   ok,没问题,反正你最骚

posted @ 2006-10-26 17:29 小小凉粉 阅读(233) | 评论 (0)编辑 收藏

首唱会上,靓颖还唱了光芒,她第一张EP的主打歌。她说这首歌正是她彼时的心里话,“谢谢你一直陪在我的身旁”。当人们拥 有高度的物质文明时,回眸一顾,精神家园却已花果飘零。于是当这个坚强自信、勇敢执著、珍爱友谊的东方女孩出现的时候,我们心甘情愿,陪她一同面对艰难、 挫折、成功、喜悦。 

当靓颖独自一人站在高台上,说这首歌使她决心成为一个好歌手 的时候,我们都知道是什么,已经有人喊出了《Hero》。当她从高台上跳下的时候,当熟悉的旋律响起来,全场静默。我敢说这时候一定有人在热泪盈眶。一曲 结束的时候,她将手抬起,伸出食指,指向台下的凉粉,然后深深一躬。 

所有靓颖的Hero版本——也许是因为这是我第一次听见现场——我觉得最为震撼——靓颖在动情。 

我在想什么?我在想,靓颖一路走来,并非青云直上,一帆风顺。沉沉黑夜里,有一步步深深浅浅的脚印。然而勇者无惧,寂寂风中,有凉粉举烛相伴,成就靓颖今夜的The One。所以,从《光芒》到《英雄》,才是那样感天动地,荡气回肠! 

那时候她在想什么?她一定想起小时候听着卡带的情景,想起参加超女中的种种,想起所有凉粉的陪伴,让她有勇气追求自己的梦想。所以,仔细去看,她跳下高台 的表情和步履是那样的义无反顾,走向凉粉的表情和步履同样是那样义无反顾。她被我们奉为“英雄”,她又把“英雄”送给了我们。 

而我们——在台下挥舞荧光棒的凉粉、守在电脑前不肯离去的凉粉——风霜雨雪中,永远是为英雄守候的身影,为靓颖担待的脊梁!

posted @ 2006-10-19 09:07 小小凉粉 阅读(296) | 评论 (0)编辑 收藏

首先是一个效果图:

login.JPG

为了不违反保密协议,偶在这里把logo和相关的东西都涂掉了,希望不会让人觉得难看....

ok,下面就开始讲述偶的coding过程:

首先捏,Dialog是分为三部分的,Window Title Bar,Content Area和Button Bar

这里的Window Title Bar素很难改动滴,偶也米改....而接下来的ContentArea和ButtonBar因为素分成两截滴,所以就要把一张背景图片拆成两截,分别设置成ContentArea和ButtonBar的背景图片鸟~~~
    protected Control createDialogArea(Composite parent) {
        Composite composite = (Composite) super.createDialogArea(parent);
        composite.setBackgroundImage(backgroundImage);
        .......
    }

    protected Control createButtonBar(Composite parent) {
        Control composite 
= super.createButtonBar(parent);
        composite.setBackgroundImage(backgroundBtmImage);
        .......
       
return composite;
    }

当然,仅仅做到这些还是远远不够滴,不信,你看~~~

login2.JPG

看到效果了咩....接下来偶们要做滴就是解决掉背景的问题,因为这个对话框里面没有Table、Tree之类的控件,于是在createDialogArea()方法中加入一行:

composite.setBackgroundMode(SWT.INHERIT_DEFAULT);

我们再来看看改变后的效果:

login3.JPG

如上图所示,介个ContentArea的背景问题已经解决鸟,下面就素重中之重滴ButtonArea鸟~~~让我们打开Dialog的源代码,看一下createButtonBar()的部分,就可以发现里面有两行:

        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
                
| GridData.VERTICAL_ALIGN_CENTER);
        composite.setLayoutData(data);

介样子怎么能行捏,偶们需要让介个Composite填满整个DialogArea,这样子才可以显示出整个背景图片,所以偶们就要在重写后的方法中加入下面一行代码:

composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, falsefalse));

现在让偶们再来看看运行后的结果:

login4.JPG

为什么会素介个样子捏?即使素把layout改成SWT.RIGHT,也不会改变介个结果...偶快要郁闷滴抓狂鸟.....

经过漫长滴测试,偶终于发现鸟,如果控件滴layoutData不grabExcessSpace的话,那么现在滴DialogArea的Composite实际大小就素两个Button加起来滴大小,所以无论如何也素不会居右对齐滴....介可怎么办捏.....如果去重写createButton方法滴话,那介个dialog滴代码可就太丑陋鸟....

在一个偶然滴机会下,偶终于发现鸟SWT.RIGHT_TO_LEFT !!!偶依稀见到鸟灿烂滴曙光!8过Composite的style素在创建时指定的,似乎米办法在后面覆盖,所以偶们只好整个滴把createButtonBar重写掉鸟~~~

    protected Control createButtonBar(Composite parent) {
        Composite composite 
= new Composite(parent, SWT.RIGHT_TO_LEFT
                
| SWT.NONE);
        
// create a layout with spacing and margins appropriate for the font
        
// size.
        GridLayout layout = new GridLayout();
        layout.makeColumnsEqualWidth 
= true;
        layout.marginWidth 
= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        layout.marginHeight 
= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
        layout.horizontalSpacing 
= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
        layout.verticalSpacing 
= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        layout.marginLeft 
= 10;
        composite.setLayout(layout);
        GridData data 
= new GridData(SWT.FILL, SWT.TOP, falsefalse);
        composite.setLayoutData(data);
        composite.setFont(parent.getFont());

        
// Add the buttons to the button bar.
        createButtonsForButtonBar(composite);
        composite.setBackgroundImage(backgroundBtmImage);
        
return composite;
    }

在上面的代码中,偶除了对偶所提到的地方进行了修改以外,还加上鸟一行: layout.marginLeft = 10;

介个素因为如果右边距过小滴话,背景图片就会被覆盖掉一些,而因为偶们用到鸟
SWT.RIGHT_TO_LEFT,所以应当设置marginLeft滴值 :-)

还有一点素8能忘记滴,就素要重写一下setButtonLayoutData(Button button)方法,因为偶们要把Button改成居右对齐:

    protected void setButtonLayoutData(Button button) {
        GridData data 
= new GridData(SWT.RIGHT, SWT.CENTER, falsefalse);
        
int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        Point minSize 
= button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
        data.widthHint 
= Math.max(widthHint, minSize.x);
        button.setLayoutData(data);
    }

然后再在createButtonsForButtonBar()方法中,把创建按钮的顺序改变一下,偶们就可以看到最开始滴那张美丽滴对话框鸟~~~虽然被偶涂改滴有些不美丽鸟~~~

现在还有个小小滴问题就素按钮距离底端滴黑框太近鸟~~介个素因为,介个Composite只有一行,所以要改变按钮距离底端滴距离,那么DialogArea滴大小就要跟着改变,而现在偶们滴DialogArea所需要滴背景图片还米改好,于是只有这样鸟~~~大家应该知道在哪里设置底边的边距吧?就素createButtonBar方法中滴那个layout.marginHeight =xxx :)

最后别忘了,整个对话框的高度,应该是Window Title Bar,Content Area和Button Bar三部分滴和。

偶已经说完鸟,如果觉得偶滴介篇文章对你有些帮助的朋友,请去支持一下偶们美丽可爱滴靓颖同学滴新专辑The One吧:)多谢!

posted @ 2006-10-16 18:11 小小凉粉 阅读(4193) | 评论 (12)编辑 收藏

IWorkbenchPreferenceConstants中有很多常量,用来配置preference settings,诸如:

OPEN_NEW_PERSPECTIVE——打开新视图的方式
DOCK_PERSPECTIVE_BAR——锁定
PerspectiveBar的位置
INITIAL_FAST_VIEW_BAR_LOCATION——表示fast view bar在一个fresh workspace中锁定的位置,This preference is meaningless after a workspace has been setup, since the fast view bar state is then persisted in the workbench
SHOW_TRADITIONAL_STYLE_TABS——表示是否在editor和view上显示传统的tab style
SHOW_PROGRESS_ON_STARTUP——是否在启动时显示progress
SHOW_TEXT_ON_PERSPECTIVE_BAR——是否在PerspectiveBar上显示文字

等等......

更改的时候
在RCP中的plugin.xml里,使用preferenceCustomization属性,例如:
CODE:

<extension
id="someproduct"
point="org.eclipse.core.runtime.products">
<product
  application="com.example.someproduct.application"
  name="Some Product">
  <property
    name="preferenceCustomization"
    value="plugin_customization.ini"/>

然后在ini文件中进行对应的设置

或者,
PlatformUI.getPreferenceStore().setDefault(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS,false);

posted @ 2006-10-08 10:04 小小凉粉 阅读(1242) | 评论 (1)编辑 收藏

先说一下AOSD的起源吧

传统的软件工程有一个不变的主题:对关注点的分解和局部化。将系统分解成为主要的功能模块,识别出关注点的其他问题,确保所有关注点的问题都能在代码的适当位置得到解决。但是关注点的分散和混杂又给代码编写和后期维护带来了很大的难度。
因此,必须有一种方法可以把关注点集中在一起,让系统开发者可以使用关注点自身的模块来描述每个关注点的行为。
AOSD,用以寻找软件系统中新的模块化特性,允许对系统中多个关注点进行独立描述,同时又能自动统一到系统中。

然后是一些常用的术语(from AOSD wiki):

concern(关注点):A concern is an area of interest or focus in a system. Concerns are the primary criteria for decomposing software into smaller, more manageable and comprehensible parts that have meaning to a software engineer.

crosscutting(横切):Note that crosscutting is a relationship between representations of concerns. Note also that it is a symmetric relationship. Therefore, if:

1. A is a representation of one a concern,
2. B is a representation of another concern, and
3. A crosscuts B,

then B also crosscuts A.

This means that the term "crosscutting concerns" is often misused in two ways: To talk about a single concern, and to talk about concerns rather than representations of concerns. Consider "synchronization is a crosscutting concern": we don't know that synchronization is crosscutting unless we know what it crosscuts. And there may be representations of the concerns involved that are not crosscutting.

aspect(方面):Aspects are one kind of concern in software development.

joint point(联接点):Join points are those elements of the programming language semantics which the aspects coordinate with. Nowadays, there are various join point models around and still new under development. They heavily depend on the underlying programming language and AO language.

In a number of presently available AOP languages, a join point is a region in the dynamic control flow of an application. Thus a join point can for instance represent

* a call to a method,
* execution of a method,
* the event of setting a field,
* the event of handling an exception ...

Join points can be picked up by an AOP program by using pointcuts to match on them. Depending on the pointcut language the AOP language provides, it may be possible to pick up more or less of those join points. Since join points are dynamic, it may be possible to expose runtime information such as the caller or callee of a method from a join point to a matching pointcut.

advice:In a number of AOP languages, advice consists of a pointcut and a body. The body executes at join points the pointcut matches. This pointcut may expose runtime information to the advice body.

pointcut:

(from Without EJB):A set of join points,defined to specify when an advice should fire.Pointcuts are often described using either regular expressions or another wildcard syntax.

(from Wiki)In a number of AOP languages, a pointcut is a predicate over dynamic join points, meaning that given a certain dynamic join point, a pointcut can either match this join point or not (at runtime). Another view of pointcuts is often, that they represent sets of join points. A pointcut may expose runtime information to a piece of advice.

Weaving:The process of coordinating aspects and non-aspects. Weaving can be done explicitly or implicitly, and can be done at a variety of times ranging from by-hand weaving when code is written, through compile-time, post-compile time and load time, up to runtime.

Without EJB中有个例子很好的解释了一下上面的术语:

public class MyBusinessObject implements BusinessObject{
public void businessMethod1() throws UnauthorizedException{
doSecurityCheck();
}
public void businessMethod2() throws UnauthorizedException{
doSecurityCheck();
}
public void requiresNoSecurityCheck() {
}
public void doSecurityCheck() throws UnauthorizedException{
}
}

这里,安全检查就是一个aspect,需要进行安全检查的这几个方法就是join point。而由于不是所有的方法都需要进行安全检查,所以就需要用pointcut来进行匹配。

下面使用了一个interceptor来将关注点模块化:

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class SecurityInterceptor implements MethodInterceptor{
public Object invoke(MethodInvocation invocation)throws Throwable{
doSecurityCheck();
return invocation.proceed();
}
public void doSecurityCheck{}
}

这里的interceptor就是advice

posted @ 2006-09-27 23:51 小小凉粉 阅读(259) | 评论 (0)编辑 收藏

需要以下的对象:
LoginDialog,用于展示状态,
LoginListener,用于监听登录状态,并根据不同的情况改变LoginDialog的显示
LoginAction,用于执行登录的业务逻辑,并且根据不同的结果来fire不同的动作。

状态一共有以下几种:
1。登录中
2。登录成功
3。登录失败
  3.1 连接失败
  3.2 用户名密码错误
  3.3 .....
4。用户取消登录

下面是代码片段:

Application;

public class Application implements IPlatformRunnable {
 
   
    
/*
     * (non-Javadoc)
     * 
     * @see org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object)
     
*/
    
public Object run(Object args) throws Exception {

        
try {

            TestLoginDialog dialog = new TestLoginDialog(Display.getCurrent()
                    .getActiveShell());
            LoginListener loginListener 
= new LoginListenerImpl(dialog);
            LoginAction action 
= new LoginAction("login");
            action.addLoginListener(loginListener);
            dialog.setLoginAction(action);

            
if (dialog.open() != Window.OK) {
                
return IPlatformRunnable.EXIT_OK;
            }
            
int returnCode = PlatformUI.createAndRunWorkbench(display,
                    
new ApplicationWorkbenchAdvisor());

            
if (returnCode == PlatformUI.RETURN_RESTART) {
                
return IPlatformRunnable.EXIT_RESTART;
            }
            
return IPlatformRunnable.EXIT_OK;
        } 
finally {
            display.dispose();
        }
    }
}


LoginListener:

public interface LoginListener extends EventListener{
    
public void loginError(String message);

    
public void loginComplete();

    
public void loginCanceled();
    
    
public void loginStarted();
    
}


LoginAction:这里要用到Job,因为登录的逻辑处理必须要在异步线程中来做,否则UI就会停住的。

public class LoginAction extends Job {
    
private LoginListener loginListener;
    
private Session session = Session.getInstance();

    
public LoginAction(String name) {
        
super(name);
    }

    
public void addLoginListener(LoginListener listener) {
        
this.loginListener = listener;
    }

    
public void fireLoginComplete() {
        loginListener.loginComplete();
    }

    
public void fireLoginStarted() {
        loginListener.loginStarted();
    }

    
public void fireLoginError(String message) {
        loginListener.loginError(message);
    }

    
public void fireLoginCanceled() {
        //write cancel login logic here
        loginListener.loginCanceled();
    }

    @Override
    
protected IStatus run(IProgressMonitor monitor) {
        login();
        
return Status.OK_STATUS;
    }

    
public boolean login() {
        fireLoginStarted();

        if (//网络连接失败) {
           
fireLoginError(Messages.getString("Session.connectionFailed"));
        } 
else {
            
if (//登录失败) {
           
fireLoginError(Messages.getString("Session.loginFailed"));
            } 
else {
                session.setAuthenticated(
true);
                fireLoginComplete();
                //处理登录动作
            }
        }
        
return session.isAuthenticated();
    }

}


LoginDialog:

这里用到了StackLayout,因为在登录的过程中,需要在显示用户名/密码的位置上,显示gif动画,所以在createDialogArea的时候,要创建一个主Composite,然后将其layout设置为StackLayout,然后创建两个Composite,将其parent都设置为主Composite,新创建的两个我将其命名为loginInfoComposite和loginAnimaComposite,顾名思义,一个用来显示登录信息,一个用来显示登录动画。

关于如何显示gif,我在这里就不多说了,因为SWT Snippet和Eclipse的SWT Example里面都有对应的例子,我在这里推荐大家去参考一下SWT Example,因为那里面是用Canvas来绘图的,这也是我们所需要的。

在使用StackLayout的时候要注意,当我们使用stackLayout.topControl = xxx的时候,还要调用stackLayout.layout()方法,否则会不起作用。

还有就是因为在登录的过程中,按钮栏应该是不可见的,但是Dialog的getButtonBar方法是protected的,所以就重写了这个方法,声明为public,返回super.getButtonBar(),虽然源码的注释中写着这个方法不应该重写,但是我想,这样子应该没问题吧。

另外,在绘制gif的下方添加一个按钮,并且addSelectionListener,当SelectionEvent发生的时候,就去触发loginAction的fireCancel方法就可以了。

细节就不描述了,下面是一些个人认为比较关键的代码片段:

    /*
     * to create login button 
     
*/
    
public static int LOGIN_ID = 9527;


    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, LOGIN_ID, Messages
                .getString(
"LoginDialog.loginbutton"), true); ]
        createButton(parent, IDialogConstants.CANCEL_ID, Messages
                .getString(
"LoginDialog.cancelbutton"), false);
    }


    @Override
    
protected void buttonPressed(int buttonId) {
        
if (buttonId == LOGIN_ID) {
            loginPressed();
        }
        
super.buttonPressed(buttonId);
    }


    protected void loginPressed() {
        //...
        loginAction.schedule();
    }

然后是LoginListener的实现类:

public class LoginListenerImpl implements LoginListener {
    
private Display display;
    
//login dialog
    private TestLoginDialog dialog;
    
//image to show on login failed
    private Image errorMessageImage = AbstractUIPlugin
            .imageDescriptorFromPlugin(Application.PLUGIN_ID,
                    IImageKeys.crodoTitleImage).createImage();
    
//error message area background
    private Color errorMessageBackground = new Color(null2552550);

    
public LoginListenerImpl(TestLoginDialog dialog) {
        
this.dialog = dialog;
        display 
= Display.getCurrent();
    }

    //因为这里需要在非UI线程中更新UI,所以要用display.syncExec()方法。
    public void loginCanceled() {
        display.syncExec(
new Runnable() {
            
public void run() {
                dialog.getStackLayout().topControl 
= dialog
                        .getLoginInfoComposite();
                dialog.getStackLayoutComposite().layout();
                dialog.animate();
                dialog.getButtonBar().setVisible(
true);
            }
        });
    }

    
public void loginComplete() {
        display.syncExec(
new Runnable() {
            @SuppressWarnings(
"deprecation")
            
public void run() {
                //我知道Thread.stop()方法已经被废弃,但是暂时没想到什么方法来中止
                //就暂时这样子用了,还请大家指教!
                dialog.getAnimateThread().stop();
                dialog.okPressed();
            }
        });
    }

    
public void loginError(final String message) {
        display.syncExec(
new Runnable() {
            
public void run() {
                dialog.getErrorMessageLabel().setText(message);
                dialog.getErrorMessageLabel().setImage(errorMessageImage);
                dialog.getErrorMessageLabel().setBackground(
                        errorMessageBackground);
                dialog.getStackLayout().topControl 
= dialog
                        .getLoginInfoComposite();
                dialog.getStackLayoutComposite().layout();
                dialog.animate();
                dialog.getButtonBar().setVisible(
true);
            }
        });
    }

    
public void loginStarted() {
        display.syncExec(
new Runnable() {
            
public void run() {
                dialog.getStackLayout().topControl 
= dialog
                        .getLoginAnimaComposite();
                dialog.getStackLayoutComposite().layout();
                dialog.animate();
                dialog.getButtonBar().setVisible(
false);
            }
        });
    }

posted @ 2006-09-25 19:02 小小凉粉 阅读(2125) | 评论 (1)编辑 收藏

如果使用了Eclipse3.2提供的自绘制功能来在table或者tree里面绘制图像或文字的时候,就必须在LabelProvider中,将对应column的返回值置空,同时需要记住的是,即使所有的column都使用自绘制功能的时候,也必须要给viewer提供一个LabelProvider,否则每一行的第一列上都会显示出对应Object的toString()方法的结果。

posted @ 2006-09-21 14:44 小小凉粉 阅读(1301) | 评论 (2)编辑 收藏

SMTP的连接和收发过程

a.建立TCP连接。
b.客户端发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令服务器端正希望以OK作为响应,表明准备接收。
c.客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行
d.协商结束,发送邮件,用命令DATA发送
e.以.表示结束输入内容一起发送出去
f.结束此次发送,用QUIT命令退出。

SMTP的基本命令集

HELO   向服务器标识用户身份
MAIL   初始化邮件传输mail from:
RCPT   标识单个的邮件接收人;常在MAIL命令后面可有多个rcpt to:
DATA   在单个或多个RCPT命令后,表示所有的邮件接收人已标识,初始化数据传输,以.结束。
NOOP   无操作,服务器应响应OK
RSET   重置会话,当前传输被取消
QUIT   结束会话


POP3简介

在POP3协议中有三种状态,认可状态,处理状态,和更新状态。当客户机与服务器建立联系时,一旦客户机提供了自己身份并成功确认,即由认可状态转入处理状态,在完成相应的操作后客户机发出quit命令,则进入更新状态,更新之后最后重返认可状态。

POP3基本命令集
USER username
PASS password   
STAT  请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数
LIST  返回邮件数量和每个邮件的大小
RETR [Msg#] 返回由参数标识的邮件的全部文本
DELE [Msg#] 服务器将由参数标识的邮件标记为删除,由quit命令执行
RSET 服务器将重置所有标记为删除的邮件,用于撤消DELE命令
NOOP 服务器返回一个肯定的响应
QUIT 更新


class POP3Demo {
   private static String POP3Server = "pop.126.com";
    private static String USERNAME = "username";//实际应用中改成真实的用户名
    private static String PASSWORD = "password";//实际应用中改成真实的密码
    public static void main(String[] args) {
        int POP3Port = 110;
        Socket client = null;
        try {
            // 向POP3服务程序建立一个套接字连接。
            client = new Socket(POP3Demo.POP3Server, POP3Port);
            // 创建一个BufferedReader对象,以便从套接字读取输出。
            InputStream is = client.getInputStream();
            BufferedReader sockin = new BufferedReader(new InputStreamReader(is));
            // 创建一个PrintWriter对象,以便向套接字写入内容。
            OutputStream os = client.getOutputStream();
            PrintWriter sockout = new PrintWriter(os, true);
            // 显示同SMTP服务程序的握手过程。
            System.out.println("S:" + sockin.readLine());
            sockout.println("user " + POP3Demo.USERNAME);
            System.out.println("S:" + sockin.readLine());
            sockout.println("pass " + POP3Demo.PASSWORD);
            System.out.println("S:" + sockin.readLine());
            sockout.println("stat");
            String temp[] = sockin.readLine().split(" ");
            int count = Integer.parseInt(temp[1]);//得到信箱中共有多少封邮件
            for (int i = 1; i < count + 1; i++) {//依次打印出邮件的内容
                sockout.println("retr " + i);
                System.out.println("以下为第" + i + "封邮件的内容");
                while (true) {
                    String reply = sockin.readLine();
                    System.out.println(reply);
                    if (reply.toLowerCase().equals(".")) {
                        break;
                    }
                }
            }

        } catch (IOException e) {
            System.out.println(e.toString());
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
            } catch (IOException e) {}
        }
    }
}

 class SMTPDemo {
    //以下三项请在使用时改成真实的信箱地址
    //并且注意,SMTPServer和receiver必须是同一个服务器
    private static String sender = "sender";
    private static String receiver = "receiver";
    private static String SMTPServer = "smtpserver";
    public static void main(String[] args) {
        int SMTPPort = 25;
        Socket client = null;
        try {
            // 向SMTP服务程序建立一个套接字连接。
            client = new Socket(SMTPDemo.SMTPServer, SMTPPort);
            // 创建一个BufferedReader对象,以便从套接字读取输出。
            InputStream is = client.getInputStream();
            BufferedReader sockin = new BufferedReader(new InputStreamReader(is));
            // 创建一个PrintWriter对象,以便向套接字写入内容。
            OutputStream os = client.getOutputStream();
            PrintWriter sockout = new PrintWriter(os, true);
            // 显示同SMTP服务程序的握手过程。
            System.out.println("S:" + sockin.readLine());
            sockout.println("helo");
            System.out.println("S:" + sockin.readLine());
            sockout.println("mail from: " + "<" + SMTPDemo.sender + ">");
            System.out.println("S:" + sockin.readLine());
            sockout.println("rcpt to: " + "<" + SMTPDemo.receiver + ">");
            System.out.println("S:" + sockin.readLine());
            sockout.println("data");
            //发送邮件标题
            sockout.println("subject: 你好");
            //发送邮件内容
            sockout.println("ni hao");
            sockout.println("wo shi li jian");
            //此处的.为特殊标记,表示邮件结束
            sockout.println(".");
            sockout.println("rset");
            sockout.println("quit");
        } catch (IOException e) {
            System.out.println(e.toString());
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
            } catch (IOException e) {}
        }
    }
}


posted @ 2006-09-18 15:11 小小凉粉 阅读(2636) | 评论 (5)编辑 收藏

Design decisions:

Most platforms require that widgets be created within the context of a specific parent, so SWT requires that a parent widget be supplied as one of its constructor arguments. Another requirement of many platforms is that certain style settings must be supplied at creation time (for example, buttons can be checkboxes, radio buttons, or simple buttons and text fields can be single- or multi-line).

Style bits are represented by int constants defined in the SWT class. Styles are then OR'ed together and passed as another constructor argument to create the initial style of a widget.

SWT works directly with the native underlying graphic resources, each SWT resource consumes a GUI resource, and timely release of that resource is essential not only for your SWT application's well-being, but also for the well-being of all other GUI programs currently running. Java's garbage collection carries no timeliness guarantees, and would make a poor manager of graphic resources for SWT. So, instead, you as programmer must assume the responsibility.

Fortunately, a widget that is a child of another widget is automatically destroyed when its parent is destroyed. This means that if you properly dispose of a shell, you do not need to dispose of each of its children because they will be disposed of automatically.

----------------------------------------------------------------------------------------

Top-level classes:

Each SWT application needs a display and one or more shells (representing each window frame).

Display: The Display object represents the connection between the application-level SWT classes and the underlying windowing system implementation.

One of the most important tasks of this class is its event-handling mechanism. The Display class maintains a collection of registered event listeners, reads events from the lower-level operating-system event queue, and delivers these events to the appropriate implementations of registered listener logic.

Shell: Every window has a shell representing the window frame with which the user interacts. The Shell object represents a window—either a top-level window or a dialog window. It contains the various controls that make up the application: buttons, text boxes, tables

----------------------------------------------------------------------------------------

Control: The Control class is the abstract superclass of all the dialog and window component classes such as Button, Label, ProgressBar, Sash, Scrollable, and Slider

Composite: Taking a bottom-up view of the world, every control has a parent that is an instance of the class Composite or one of its subclasses. The class Shell, which represents the top-level windows of your application, is a subclass of Composite.

Stated another way, this time from the top down, a display contains a list of top-level shells, where each shell is the root of a tree composed of composites and controls. Composites can contain other composites, allowing the tree to have arbitrary depth. If the child of a shell is another shell, the child is commonly called a dialog shell. A dialog shell always stays in front of the parent shell.

posted @ 2006-09-18 15:09 小小凉粉 阅读(250) | 评论 (0)编辑 收藏

ModalessDialog:

public class ModalessDialog extends Dialog {
 public ModalessDialog(Shell arg0) {
  super(arg0);
  setShellStyle(SWT.SHELL_TRIM | SWT.MODELESS | SWT.RESIZE | SWT.MAX);
 }
}


程序中需要双击摄像头,然后弹出的对话框中显示摄像头所捕捉的画面,原来是这样写的:

  deviceTab.getViewer().addDoubleClickListener(
    new IDoubleClickListener() {
     public void doubleClick(DoubleClickEvent event) {
      StructuredSelection selection = (StructuredSelection) event
        .getSelection();
      DeviceDataDialog dialog = new DeviceDataDialog(event
        .getViewer().getControl().getShell());
      dialog.open();
     }
    });

但是这样子出来的对话框,会始终保持在最前端显示。后来改成

DeviceDataDialog dialog = new DeviceDataDialog(null);

就可以了
也许是因为原先的程序中,对话框和主窗口使用同一个Shell所造成的吧

posted @ 2006-09-18 15:09 小小凉粉 阅读(987) | 评论 (0)编辑 收藏

因为RCP的界面也是使用MVC模式的,于是想操作TableViewer、TreeViewer的时候,不应该直接对Viewer进行操作,而是应该操作viewer的input。修改以后,调用一下viewer.refresh()方法就可以了。

今天碰到的问题是,在一个widget中,使用

viewer.setInput(DisplayConst.publishingDevices.values());

可以顺利更新

而在另外一个widget中,使用

  viewer.setInput(DisplayConst.locationTable.get(this.getUserName()));

就不能正常更新了。

测试了半天,又想了一下才明白,viewer.setInput以后,我们只能够修改input的内容,而不能修改input这个对象内存地址的值。就和方法调用在java中只能传值调用一样了。

posted @ 2006-09-18 15:08 小小凉粉 阅读(717) | 评论 (0)编辑 收藏

为了批量发布设备,需要在一个窗口中为设备命名,设定其类型等,要用到Combo,所以就用了CellEditor

用CellEditor还是很方便的,有CheckboxCellEditor,ComboBoxCellEditor,LabelCellEditor,TextCellEditor等等。

首先把TableColumn的名称做成String数组,调用viewer.setColumnProperties()方法

然后做一个CellEditor数组,数组中的每一个CellEditor都对应着每一个Column

然后实现ICellModifier接口,做一个自己的CellModifier,并调用viewer.setCellModifier()方法

接口中有三个方法:

1.public boolean canModify(Object element, String property)
用来判断哪一个属性可写
2.public Object getValue(Object element, String property)
返回某个属性的值
3.public void modify(Object element, String property, Object value)
为某个属性赋值

昨天碰到了很多异常,情况如下:

1.ComboCellEditor 中对应的是Integer类型的值,如果用了String的话,就会有异常抛出。

2.tableviewer的input中,对象的很多属性没有赋初始值,由此而导致了在CellModifier里面调用get或者set方法时,出现了空指针异常。

3.update tableviewer。今天上午才找到table.addFocusListener方法,而且要在focusGained方法中进行更新。应该是由于编辑Cell的时候,focus从Table转移到了Cell上,所以要用focusGained方法吧。

posted @ 2006-09-18 15:08 小小凉粉 阅读(1365) | 评论 (0)编辑 收藏

首先下载soap,把soap.war放到tomcat/webapp/目录下,在classpath下面加入soap.jar、mail.jar和 activation.jar,然后创建一个Service和Client,把Service.class放到 tomcat/webapp/soap/WEB-INF/classes目录下,然后把mail.jar和activation.jar放到 tomcat/webapp/soap/WEB-INF/lib下面,并写一个配置文件用于部署服务。

<isd:service
   xmlns:isd="http://xml.apache.org/xml-soap/deployment"
   id="urn:service" checkMustUnderstands="true">
      <isd:provider type="java" scope="Request" methods="setAlarm">
      <isd:java class="work.Service" static="false"/>
   </isd:provider>
</isd:service>


上面的work.Service是类的全名,setAlarm是提供的服务名,urn:service是URI。再写一个脚本来调用配置文件部署服务

java org.apache.soap.server.ServiceManagerClient
http://localhost:8080/soap/servlet/rpcrouter deploy deploy.xml

启动Tomcat之后,启动脚本,然后执行Client代码就可以了,Client的主体代码很简单,代码里面就不加入注释了。
  
    Call call = new Call ();
    call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
    call.setTargetObjectURI ("urn:service");
    call.setMethodName ("setAlarm");
    Parameter param = new Parameter("alarm", String.class, alarm, Constants.NS_URI_SOAP_ENC);
    Vector paramList = new Vector();
    paramList.addElement(param);
    call.setParams (paramList);
    URL url = new URL ("http://localhost:8080/soap/servlet/rpcrouter");
    Response resp = call.invoke (url, "");
    if (!resp.generatedFault()) {
      // Extract Return value
      Parameter result = resp.getReturnValue ();
      String greeting = (String) result.getValue();
      return greeting;
    }
    else {
      //  Extract Fault Code and String
      Fault f = resp.getFault();
      String faultCode = f.getFaultCode();
      String faultString = f.getFaultString();
      System.err.println("Fault Occurred (details follow):");
      System.err.println("Fault Code:  "+faultCode);
      System.err.println("Fault String:  "+faultString);
      return new String ("Fault Occurred.  No greeting for you!");
    }

posted @ 2006-09-18 15:06 小小凉粉 阅读(362) | 评论 (0)编辑 收藏

昨天写完程序并部署Service之后,一直都在抛出接口不匹配的异常,于是我就写了个简单的接口,只传入一个String类型的参数,结果运行正常。然后我又写了个只传入Integer类型参数的接口,果不出所料,又发生了接口不匹配的异常。接下来我就开始改Client端代码:

params.addElement(new Parameter("eventStatus",Integer.class, new Integer(1), null));
params.addElement(new Parameter("eventStatus",int.class, new Integer(1), null));
params.addElement(new Parameter("eventStatus",int.class, 1, null));
params.addElement(new Parameter("eventStatus",Intege.class, 1, null));
结果统统失败,弄的我都要抓狂了。

今天到了公司以后,跟组长说了这件事情,组长说让我换用AXIS试试看,我到ws.apache.org/axis上面看了看文档,在user guide里面给出的例子和我的代码差别很大,我就只好按着它的例子重新改代码

写完以后,配环境变量配的快要抓狂……部署的时候又是一头雾水……最后始终没有成功……最后回到宿舍才想到,AXIS和Apache SOAP Server不过都是服务器而已,不应该存在规范上的区别,也就是不应该会影响到客户端的程序,于是我就按照最开始的代码,把Service部署好,启动 Tomcat,从WSDL中找到对应的信息

<wsdl:service name="ServiceService">
 <wsdl:port binding="impl:serviceSoapBinding" name="service">
  <wsdlsoap:address location="http://localhost:8080/axis/services/service" />
 </wsdl:port>
</wsdl:service>

在xml配置文件中,把location赋值给URL,把name赋值给TargetObjectURI,运行Client,一切OK
不知道是不是因为机器的问题,在公司的思路远远不如在宿舍啊

不过今天至少让我很熟练的掌握了如何手工部署AXIS服务,创建一个wsdd文件,我把它命名为deploy.wsdd

<deployment name="lijian" xmlns="http://xml.apache.org/axis/wsdd/"
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <service name="service" provider="java:RPC">
    <parameter name="className" value="Service" />
    <parameter name="allowedMethods" value="setAlarmInfo" />
  </service>
</deployment>


把这个文件放到Tomcat/webapps/axis/WEB-INF/目录下,把service的类放到WEB-INF/classes/目录下,把 axis.jar;jaxrpc.jar;commons-logging-1.0.4.jar;commons-discovery-0.2.jar;saaj.jar 放到classpath里面,启动Tomcat之后,到webapps/axis/WEB-INF目录下运行:
java org.apache.axis.client.AdminClient deploy.wsdd
之后可以访问
http://localhost:8080/axis/
来查看刚才部署的service对应的wsdl了

posted @ 2006-09-18 15:05 小小凉粉 阅读(449) | 评论 (0)编辑 收藏

在web环境下,Quartz可以通过配置文件来完成后台的作业调度,不必手工创建Trigger和Scheduler,其步骤如下:

首先将quartz.jar,以及lib目录下面core和optional两个目录中的所有jar全都放入项目WEB-INF\lib目录下

job就是一个简单的java类,这里的功能就是输出当前的时间了。

import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class Helloworld implements Job{
 public Helloworld() {
 }

 private static Log _log = LogFactory
   .getLog(Helloworld.class);

 public void execute(JobExecutionContext context)
   throws JobExecutionException {
  _log.info("Hello World! - " + new Date());
 }
}

然后编写quartz.properties文件,这个文件的默认名称就是quartz.properties,如果启动项目的时候,Quartz没有在工程中找到该文件,就会从自己的jar包下面读取其默认的properties文件,其内容如下:

org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = one

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount =  2
org.quartz.threadPool.threadPriority = 4

org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss MM/dd/yyyy}
org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss MM/dd/yyyy} with resulting trigger instruction code: {9}

org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileName = quartz_job.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownhook.cleanShutdown = true

上面的

org.quartz.plugin.jobInitializer.fileName = quartz_job.xml

是用来配置定义job文件的名称。

然后编写quartz_job.xml,

<?xml version="1.0" encoding="UTF-8"?>
<quartz>
  <job>
    <job-detail>
      <name>helloworld</name>
      <group>group1</group>
      <job-class>Helloworld</job-class>
    </job-detail>
    <trigger>
      <cron>
        <name>test</name>
        <group>group1</group>
        <job-name>helloworld</job-name>
        <job-group>group1</job-group>
        <cron-expression>0 0/1 * * * ?</cron-expression>
     </cron>
    </trigger>
  </job>
</quartz>

可以看到,在配置文件中把jobdetail和trigger都作了完整的定义,并组合成一个job。下面,我们把上面两个文件都放入/WEB-INF/classes目录下,然后按照api中的说明修改一下web.xml。

     <servlet>
         <servlet-name>
             QuartzInitializer
         </servlet-name>
         <display-name>
             Quartz Initializer Servlet
         </display-name>
         <servlet-class>
             org.quartz.ee.servlet.QuartzInitializerServlet
         </servlet-class>
         <load-on-startup>1</load-on-startup>
         <init-param>
             <param-name>config-file</param-name>
             <param-value>/quartz.properties</param-value>
         </init-param>
         <init-param>
             <param-name>shutdown-on-unload</param-name>
             <param-value>true</param-value>
         </init-param>
     </servlet>

这样,在启动Tomcat的时候,QuartzInitializerServlet这个Servlet就会自动读取quartz.properties这个配置文件,并初始化调度信息,启动Scheduler。
我在这里用的是Quartz1.5.0,在1.5.1中新增加了QuartzInitializerListener,但是似乎有些问题,始终启动不起来,而且更过分的是,它的api居然写错了,在<listener-class>这个标记中,用了 QuartzInitializerServletListener,就算把机器砸了,它也找不到这个类啊!

现在就大功告成了
一个Job类,一个quartz.properties文件,一个quertz_job.xml文件,还有修改一下web.xml文件,很简单呀!

不过看起来简单,解决的过程却很郁闷,单单是考虑如何在后台进程中运行Servlet就花了好长时间,后来查资料以后才知道可以用Listener或者是启动时运行的Servlet来完成,看来自己的底子还是不扎实的.

另外就是在Tomcat出现问题的时候,居然忘了到logs下面去看日志,这个疏忽是不可原谅的!以后要牢牢记住!

posted @ 2006-09-18 15:05 小小凉粉 阅读(1137) | 评论 (0)编辑 收藏

在验证用户登录的时候,各个类调用的顺序如下所示:

authenticationProcessionFilter(AuthenticationProcessingFilter)---->

authenticationManager(ProviderManger)---->

daoAuthenticationProvider(DaoAuthenticationProvider)---->

userDetailsService(UserDetailsService)

在最底层的UserDetailsService接口中,提供了loadUserByUsername这个方法,我们只需要实现这个接口,并实现接口中的方法,就可以使用自己的验证功能了。该方法传入的参数是String username,返回类型是UserDetails,很显然,我们需要通过自己的dao,根据username来得到自定义的user类型,然后把它封装到UserDetails里面去,然后返回。

另外,在UserDetail这个类里面,有一个GrantedAuthority[] 类型的属性,用来存放该用户所对应的权限,我们在loadUserByUsername这个方法里面,同样也需要得到该用户的权限,并把它赋给返回的UserDetails。

假如用户对应的类名为UserInfo,权限对应的类名为Roles,在UserInfo中有一个变量

private Set roles;

在得到权限信息的时候,因为它是集合,所以可以使用延迟加载功能,读取的时候先从缓存中取数据,如果取不到的话,就调用UserInfo.getRoles()方法,这个时候就会到数据库中取数据了,取到以后,再把数据放到缓存中。

posted @ 2006-09-18 15:04 小小凉粉 阅读(272) | 评论 (0)编辑 收藏

1. SOAP--Simple Object Access Protocal

SOAP is a lightweight protocol intented to exchanging structured information in a decentralized, distributed environment.The two major goals for SOAP is simplicity and extensibility.

SOAP is widely used for XML messaging as it :

    defines thin layer on top of widely understood HTTP 
    is flexible and extensible 
    enjoys broad industry and developer community support

Main uses of SOAP are for

    messaging: sending XML data orders, invoices, forms 
    RPC: invoking services querying data sources, transacting

2. WSDL--Web Service Definition Language

As the communication protocols and message formats are standardized in the web community, it becomes increasingly possible and important to be able to describe the communication s in some structured way.WSDL addresses this need by defining an XML grammar for describing network services as collections of communication endpoints capable of exchanging messages.

3.  UDDI-- Universal Description, Discovery, and Integration

UDDI protocol is a central element of the group of related standards that comprise the Web services stack. The specification defines a standard method for publishing and discovering the network-based software components of a service-oriented architecture.

4.  the relationship between SOAP,WSDL and UDDI

web service client 需要定位另一个应用程序或者是网络上的某一段业务逻辑, client 通过 name catagory identifier 或者 specification 来从 UDDI registry 中查询服务,定位以后, client UDDI registry 中得到 WSDL 文档的位置信息。在 WSDL 文档的 XML schema 中包含了如何访问 web service 和请求信息的格式, client 按照 xml schema 的格式来创建一个 soap 消息,并向 host 发送请求。

posted @ 2006-09-18 15:03 小小凉粉 阅读(292) | 评论 (0)编辑 收藏

用一个类来存放applicationContext:
public class ContextHolder {
  private final static ContextHolder instance = new ContextHolder();
  private ApplicationContext ac;
  private ContextHolder() {
  }
  public static ContextHolder getInstance() {
    return instance;
  }
  public synchronized void setApplicationContext(ApplicationContext ac) {
    this.ac = ac;
  }
  public ApplicationContext getApplicationContext() {
    return ac;
  }  
}

然后写一个servlet,继承自org.springframework.web.context.ContextLoaderServlet,并配置web.xml,让它在tomcat启动时自动运行。然后在它的init方法中,加入如下的代码:
WebApplicationContext context = WebApplicationContextUtils.
    getWebApplicationContext(this.getServletContext());
ContextHolder.getInstance().setApplicationContext(context);

posted @ 2006-09-18 14:57 小小凉粉 阅读(859) | 评论 (0)编辑 收藏

Can you foresee everything? No. Are the decisions you make today final? No. It's practically impossible to think everything or know everything in the beginning of a project. You will learn more as a project goes on. However, you can use your experience or experiences of others to guide you in a certain direction. You can make decisions that might minimize changes tomorrow.

posted @ 2006-09-18 14:54 小小凉粉 阅读(177) | 评论 (0)编辑 收藏

EventHandler要抽象出一个接口来,然后根据不同的需要实现不同的handler,不然就无法在服务器reply以后通知UI更新,但至于是否要在UI中再生成异步线程来做这件事情,还要通过编码测试一下。

不过目前我的感觉是不需要再生成异步线程了,因为底层Peercore的操作本身就是异步的,不需要等待它的方法操作完毕以后再返回,应该只需要把UI中要更新的控件作为参数传到EventHandler里面去,这样handler就可以通知UI更新了——打住!RCP非UI的线程是无法操作UI线程的!!只能通过UIJob或者是Display.asnyexec()方法来更新UI,所以....还是要定义很多的UIJob的子类的......

posted @ 2006-09-18 14:54 小小凉粉 阅读(315) | 评论 (0)编辑 收藏