« 1 23» Pages: ( 1/3 total )
本页主题: 用Eclipse RCP & ECF 实现 Google Talk客户端【原创】 打印 | 加为IE收藏 | 收藏主题 | 上一主题 | 下一主题

reload_cn

头衔:CS高手 CS高手
状态: 离线
级别: CEC总版
精华: 4
发帖: 436
威望: 72 点
财富: 458 元
在线时间:74(小时)
注册时间:2005-09-21
最后登录:2008-12-02

用Eclipse RCP & ECF 实现 Google Talk客户端【原创】

声明:该文章在本人的Blog和该论坛同时发布,并非转载

大家用过Google Talk吗?它是Google推出的一个IM,通讯协议是我们熟悉的Jabber协议。我通过这篇文章给大家简单介绍一下如何利用ECF实现一个Google Talk客户端。源代码下载:http://www.blogjava.net/Files/reloadcn/Chat.rar

1.准备工作
先下载ECF:
www.eclipse.org/ecf

为了能够测试我们这个客户端是否能正常运行,我们还需要下载一个Goolge Talk客户端:www.google.com/talk

当然,我们想要登陆Google的服务器必须拥有一个GoogleMail帐号,由于现在GoogleMail帐号不是随便申请的,需要GoogleMail用户推荐才能申请,但也能通过一些网站进入GoogleMail申请页面,大家可以上网搜索一下,我在这里就不多说了。




我们要建立一个Google Talk的客户端,需要了解一些ECF的知识。大家可以去Eclipse主站获得更多的信息。

2.建立一个RCP Mail Example

我们先选择创建Plugin Project,取名为“Chat”,当到向导页的第二页的时候,注意在“Would you to create a rich client platform”选项选择“yes”,这样确保你创建的是一个RCP工程,见下图:





当到最后一页的时候,选择Mail Template:




完成向导后我们将会得到一个简单的RCP工程。

3.登陆的代码

1)连接前工作
ECF是一个基于Eclipse的通讯平台,它其中一部分实现了Jabber协议。ECF有一个ClientContainer概念,其实就相当于一个维护客户端的对象,它具有连接、断开连接服务的方法,并且能够添加一些通讯中的事件监听器。所以,我们创建Google Talk客户端首先就要拥有这么一个对象,而且它在整个程序生命周期中是唯一的。
让我们修改一下ChatPlugin中的代码:
首先,我们在这个类里增加一个私有变量clientContainer,并且给他加上Getter、Setter方法:

XMPPClientSOContainer clientContainer;
? public XMPPClientSOContainer getClientContainer() {
? ?   return clientContainer;
? }

? public void setClientContainer(XMPPClientSOContainer clientContainer) {
? ?   this.clientContainer = clientContainer;
? }


OK,试想一下,当我们在登陆Google服务器的时候才会去使用这个clientContainer去连接服务器,而且我们登陆的用户信息是需要保存下来的,以供后面的代码访问,所以这个clientContainer的生成方式应该是Lazy的,并且我们还需要建立一个我们登陆帐户的变量:

? private ID userID;

? public ID getUserID() {
? ?   return userID;
? }

? public void setUserID(ID userID) {
? ?   this.userID = userID;
? }


ECF中针对用户的信息是用ID来表示的,它是一个接口,ECF已经实现了一个XMPPID,正好是我们Jabber帐户需要的。

clientContainer有一个connect方法去登陆服务器,而且在连接后不再具有其他什么动作。读者会问:那什么时候通知我们连接成功呢?并且用户在服务器端的好友怎么获得呢?

clientContainer只负责连接,上述的那些事情都属于在连接服务器过程中或者连接后,服务器反馈给客户端的信息,这些信息需要我们给clientContainer设置监听器去捕获。

其中有一个监听器名为ISharedObjectContainerListener,这个监听器能够捕获一些在连接过程和断开连接过程中的事件,比如SharedObjectConnectedEvent (连接成功事件)、SharedObjectDisconnectedEvent (断开连接成功事件),如果我们需要在客户端连接上服务器后做点什么,那这个监听器是必须的。

clientContainer.addListener(
? ? ? ? ? ? new ISharedObjectContainerListener() {
? ? ? ? ? ? public void handleEvent(IContainerEvent evt)
? ? ? ? ? ? ?   if (evt instanceof ISharedObjectContainerConnectedEvent) {
? ? ? ? ? ? ? ? ? ? ? // 连接服务器成功后做点什么呢?
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ?   if (evt instanceof ISharedObjectContainerDisconnectedEvent) {
? ? ? ? ? ? ? ? ? ? ? // 断开服务器成功后做点什么呢?
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }

? ? ? ? ? ? }, null);


2)开始连接服务器

我们看看clientContainer有一个connect方法。

这个方法需要有两个参数:用户的ID、连接上下文

用户ID我们刚才已经说过了,它是ECF提出的一个概念,我们可以通过IDFactory生成它:

userID = IDFactory.getDefault().makeID(
? ? ? ? ? ? ? ? ? ? ? ? ? clientContainer.getConnectNamespace(),
? ? ? ? ? ? ? ? ? ? ? ? ? getUserName());


大家发现了吗,上面代码中的makeID方法需要两个参数,一个参数我们可以从clientContainer获得,它是连接名字空间,我的理解是某种协议。第二个是用户名,这个参数在我们这里是Google Talk的帐号,也就是GMail帐号,但是目前我们还没有办法从外部获得,这我会在下面的内容中提到,到时候就可以将这个程序串起来,大家现在可以把它看作已经具备某些值。

好,我们已经有了ID,现在看看什么如何创建上下文。连接上下文其实很简单,我们可以这样理解:就是在我们连接的时候,clientContainer会向客户端所取一些相关的信息,比如nikename,password,这样理解起来就不麻烦了,而且在我们的这个Google Talk客户端中,它也只会向我们索取password和username,来看看我们代码就更清楚了:

clientContainer.connect(userID, new IConnectContext() {

? ? ?   public CallbackHandler getCallbackHandler() {
? ? ? ? ? return new CallbackHandler() { ?
? ? ? ? ? ? ? public void handle( Callback[] callbacks)throws IOException,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?   UnsupportedCallbackException {
? ? ? ? ? ? ? ? ?   if (callbacks == null) return;
? ? ? ? ? ? ? ? ? ? for (int i = 0; i < callbacks.length; i++) {
? ? ? ? ? ? ? ? ? ? ? ? if (callbacks【i】 instanceof NameCallback) {
? ? ? ? ? ? ? ? ? ? ? ?   NameCallback ncb = (NameCallback) callbacks【i】
? ? ? ? ? ? ? ? ? ? ? ?   ncb.setName(getUserName());
? ? ? ? ? ? ? ? ? ? ? ?   } else
? ? ? ? ? ? ? ? ? ? if (callbacks【i】 instanceof ObjectCallback) {
? ? ? ? ? ? ? ? ? ? ? ObjectCallback ocb = (ObjectCallback) callbacks【i】
? ? ? ? ? ? ? ? ? ? ? ocb.setObject(password);
? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?   }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? };
? ? ? ? ? ? ? ? ? ? ? ? ? ?   }

? ? ? ? ? ? ? ? ? ? ? ? ? });


到目前为止,我们已经完成了连接这个环节,我们将这些代码都封装到ChatPlugin的login方法中,到时候通过外部的操作好调用。

4.开始登陆

我们利用SWT Dialog建立一个简单的登陆对话框:




这个类需要有几个属性:用户帐号、用户密码、对话框返回值。

当我们点击了Login后,对话框关闭,并将文本中的值赋给帐号和密码这两个属性,返回值设为SWT.OK;如果是Cancel的话那我们就直接关闭对话框,返回值设置为SWT.CANCEL。

我们再到Mail RCP中提供的MessagePopupAction类中修改它的run方法:

public void run() {
? ?   if(ChatPlugin.getDefault().getClientContainer() != null) {
? ? ? ? MessageDialog.openInformation(window.getShell(),"Info","已经登陆了,请先注销再重新登陆");
? ? ? ? return;
? ?   }
? ?   LoginDialog dialog = new LoginDialog(window.getShell(),SWT.NONE);
? ?   dialog.open();
? ?   if(dialog.getDialogResult() == SWT.OK){
? ? ? ? ChatPlugin.getDefault().setPassword(dialog.getPassword());
? ? ? ? ChatPlugin.getDefault().setUserName(dialog.getUser());
? ? ? ? ChatPlugin.getDefault().login();
? ?   }
? }


代码逻辑很清楚。当我们点击这个按钮的时候,就会弹出登陆的对话框,然后我们输入信息后就可以正常登陆了。

注意后面的代码,我们将ChatPlugin中的用户名和密码先设置好后再调用登陆方法。如果登陆失败的话会在ChatPlugin的login方法中捕获到连接失败的异常。

5.获得我的好友们

怎么去获得我的好友呢?

刚才已经在前面提到了一点:clientContainer只负责去连接,而那些网络的事件需要我们去增加监听器捕获。获得好友也是一样的,我简单说一下。

clientContainer可以通过getAdapter去获得一个IPresenceContainer类型对象,这个对象可以增加监听获得好友信息的监听器,不仅如此,它还可以获得消息发送对象和消息的监听对象,这我会在后面介绍。
我们要想获得好友信息,就应该通过clientContainer获得IPresenceContainer对象,然后给它增加一个能够获得好友事件的监听器。

问题在这里,我们应该在什么时候去获得这个对象呢?那这个监听器接口是不是需要一些现有类去实现呢?

先说第一个问题:我们什么时候去获得这个对象,并为它增加监听器

一般情况下,我们在登陆成功以前的时候是不会去捕获我们的好友列表的消息的,而且也捕获不到,服务器在没有验证我们的客户端时,是不会发过来的,所以我们需要在登陆成功后去获得这个对象,并为它增加一个监听去。而这个对象也是需要作为一个私有变量存放起来,供其他类去访问。所以我们需要在第3节中提到了监听登陆成功的方法中写这段代码,由于篇幅问题,我不在这里给出代码片段,读者可以去看源代码。

看看第二个问题:谁需要实现这个监听器?

我们常见的IM中,都是有一个列表控件保存我们当前的用户信息的,所以我们在获得好友列表后就需要往某些Viewer中增加一些内容,来表示这是我们的好友列表。

我在这个客户端中,采用了一个View作为显示好友列表的控件,该View名为SimpleView,这个View具有一个TableViewer。该类的具体生成方法我不在多说,大家可以看看源代码,我只说一下这个View如何去实现监听获得好友信息的事件的。

我们让它实现IPresenceListener接口,并修改handleSetRosterEntry方法:

public void handleSetRosterEntry(IRosterEntry entry) {
? ?   final IRosterEntry e1 = entry;
? ?   Display.getDefault().asyncExec(new Runnable() {
? ? ? ? public void run() {
? ? ? ? ? if(e1.getInterestType() ==InterestType.BOTH){
? ? ? ? ? roseters.add(e1);
? ? ? ? ? if(viewer.getInput() != roseters) viewer.setInput(roseters);
? ? ? ? ? viewer.refresh();
? ? ? ? ? }
? ? ? ? }
? ?   });
? }


这个方法就是截获获得好友信息的接口函数,entry表示的是从服务器获得的一些和客户端好友有关的信息,每当获得一个,判断一下这个好友是否都在双方的好友名单中,如果不是那就不要增加它;反之,我们就会把这个entry放到一个名位roseters的List对象中,然后刷新viewer。这里的viewer是刚才我们提到的TableViewer,做过SWT/JFace的读者一定知道,这个类需要我们去为它添加两个接口实现,一个是ContentProvider接口,一个是LabelProvier接口,这两个接口代码读者可以看看我的源码,这里就不写了。如果您对SWT/JFace不熟悉的话也没关系,这方面的资料很多。
看看我们登陆后获得好友列表是什么样的:





6.监听消息

有了刚才增加好友的经验,我们现在就很容易解决这个问题。
同样,监听消息还是由IPresenceContainer对象增加的监听器来截获的。
而我让我们工程中一个名为View的类实现了这个监听器,并且实现这个接口的方法如下:

public void handleMessage(ID fromID, ID toID, Type type, String subject, String messageBody) {
? ?   final ID id = fromID;
? ?   if(type == Type.CHAT){
? ?   final String message = messageBody;
? ?   Display.getDefault().asyncExec(new Runnable(){
? ? ? ? public void run(){
? ? ? ? ? try {
? ? ? ? ? ?   if(id.toURI().compareTo(chaterID.toURI()) ==0){
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? String s = chaterID.toURI().getUserInfo().toString();
? ? ? ? ? ? ? ? s += " say: " + message +"\n";
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? showText.append(s);
? ? ? ? ? ? ? ? View.this.getSite().getWorkbenchWindow()
? ? ? ? ? ? ? ? .getWorkbench().getActiveWorkbenchWindow()
? ? ? ? ? ? ? ? .getActivePage().activate(
? ? ? ? ? ? (IViewPart)ChatPlugin.getDefault().getMessageDialogForID(chaterID));
? ? ? ? ? ?   }
? ? ? ? ? } catch (URISyntaxException e) {
? ? ? ? ? ?   // TODO Auto-generated catch block
? ? ? ? ? ?   e.printStackTrace();
? ? ? ? ? }
? ? ? ? }
? ?   });}
? ?  
? }


可能读者这会看上面的代码会一头雾水。我解释一下:
变量chaterID是一个ID类型的,它其实是从刚才我们好友列表中,双击某一项时生成这个View对象的时候传进来的,让我们看看SimpleView 中的双击action的代码:

doubleClickAction = new Action() {
? ? ? ? public void run() {
? ? ? ? ? ISelection selection = viewer.getSelection();
? ? ? ? ? IRosterEntry entry = (IRosterEntry) ((StructuredSelection) selection)
? ? ? ? ? ? ? ? .getFirstElement();
? ? ? ? ? View chatView = (View) ChatPlugin.getDefault()
? ? ? ? ? ? ? ? .getMessageDialogForID(entry.getUserID());
? ? ? ? ? if (chatView != null) {
? ? ? ? ? ?   SampleView.this.getSite().getWorkbenchWindow()
? ? ? ? ? ? ? ? ? .getWorkbench().getActiveWorkbenchWindow()
? ? ? ? ? ? ? ? ? .getActivePage().activate(chatView);
? ? ? ? ? }
? ? ? ? }
? ?   };


可以看出来,当我们双击某个好友的时候,就会从entry中得到他的ID,然后生成一个View,并将ID给View,所以View的chaterID就时这么来的。

接着上面的解释:
showText变量其实是一个StyleText对象,他专门负责显示聊天信息,而下面那一长段代码读者大可不必理会,那是为了使一个好友对应一个View而做的一些工作,大概了解即可,也可以去看源代码获得更多的信息。

7.发送消息

让我们看看View类中的一段代码:

messageText.addKeyListener(new KeyListener(){

? ? ? ? public void keyPressed(KeyEvent e) {
? ? ? ? ?
? ? ? ? }

? ? ? ? public void keyReleased(KeyEvent e) {
? ? ? ? ? if(e.character == '\r'){
? ? ? ? ? ?   sendMessage(messageText.getText());
? ? ? ? ? ?   messageText.setText("");
? ? ? ? ? }
? ? ? ? }
? ? ? ?
? ?   });


不难看出这段代码的意思:当遇到输入字符为回车的时候,就调用sendMessage方法:

public void sendMessage(String message) {
? ?   if(this.getChaterID() == null) return;
? ?   String s = "你说:";
? ?   s+= message;
? ?  
? ?   ChatPlugin.getDefault().getPresenceContainer().getMessageSender()
? ? ? ? ? .sendMessage(ChatPlugin.getDefault().getUserID(),chaterID, null, null, message);
? ?  
? ?   showText.append(s + "\n");
? }


sendMessage方法是从ChatPlugin中获得IPresenceContainer的messagesender去发送消息的,发送消息的函数第一个参数是发送者的ID,第二个是接收者的ID(chaterID已经在上面讲过了获取的来源),最后一个是发送的消息,中间两个参数一个消息类型和标题,他们可以为空。

8.结束语
通过我们上面所说的如何去登陆、获得好友列表、接收消息和发送消息,我们已经能够简单地创建一个Google Talk的客户端了,但是还有很多功能没有实现,比如添加好友、监听好友状态改变等等,这些都需要大家去增加。就讲到这里,我们下次再见。

本帖最近评分记录:
  • 财富:10(yy2008)
  • 威望:5(isaacxu)
  • 顶端 时间: 2005年11月23日 02:27 | [楼 主]
    realone

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 54
    威望: 16 点
    财富: 263 元
    在线时间:5(小时)
    注册时间:2005-11-21
    最后登录:2008-12-02

    好文,不愧是大虾,有时间学习一下:),我收藏了
    顶端 时间: 2005年11月24日 11:43 | 1 楼
    isaacxu

    状态: 离线
    级别: CEC贵宾
    精华: 0
    发帖: 21
    威望: 33 点
    财富: 106 元
    在线时间:1(小时)
    注册时间:2005-10-30
    最后登录:2005-11-26

    有此帖,本版兴旺就有了保证。
    顶端 时间: 2005年11月24日 18:09 | 2 楼
    水狐

    头衔:业余砌砖的 业余砌砖的
    状态: 离线
    级别: CEC版主
    精华: 1
    发帖: 551
    威望: 72 点
    财富: 24 元
    在线时间:87(小时)
    注册时间:2005-11-24
    最后登录:2008-11-19

    好! 赞哦。

    要是有QQ就好咯。
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    SWT学习中……
    SWT学习中……
    顶端 时间: 2005年11月25日 04:00 | 3 楼
    reload_cn

    头衔:CS高手 CS高手
    状态: 离线
    级别: CEC总版
    精华: 4
    发帖: 436
    威望: 72 点
    财富: 458 元
    在线时间:74(小时)
    注册时间:2005-09-21
    最后登录:2008-12-02

    QQ倒是有,你去看看luma QQ的源代码吧,luma QQ曾经有一个Eclipse 插件版本
    顶端 时间: 2005年11月25日 15:54 | 4 楼
    jetgeng

    状态: 离线
    级别: CEC版主
    精华: 1
    发帖: 199
    威望: 31 点
    财富: 94 元
    在线时间:51(小时)
    注册时间:2005-10-27
    最后登录:2008-05-16

    很爽的一篇文章,顶一下。
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    爱软件,爱eclipse
    我的blog:http://www.blogjava.net/JetGeng/
    顶端 时间: 2005年12月13日 12:32 | 5 楼
    金鳞

    状态: 离线
    级别: CEC版主
    精华: 2
    发帖: 247
    威望: 48 点
    财富: 191 元
    在线时间:50(小时)
    注册时间:2005-11-24
    最后登录:2007-05-14

    恩,开拓了眼界
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    金鳞岂是池中物,一遇风云便化龙
    顶端 时间: 2005年12月13日 17:56 | 6 楼
    gohands

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 242
    威望: 15 点
    财富: 113 元
    在线时间:25(小时)
    注册时间:2005-12-06
    最后登录:2006-12-09

    牛人啊!
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    come on,baby
    我是新手,我怕谁!
    顶端 时间: 2005年12月14日 12:01 | 7 楼
    金鳞

    状态: 离线
    级别: CEC版主
    精华: 2
    发帖: 247
    威望: 48 点
    财富: 191 元
    在线时间:50(小时)
    注册时间:2005-11-24
    最后登录:2007-05-14

    我有个问题想问一下,如果想连接其他的Jabber服务器怎么办?在哪里设置?
    因为我看了一下org.eclipse.ecf.provider.xmpp.container.XMPPClientSOContainer这个类,
    他里面有个protected static final java.lang.String GOOGLE_SERVICENAME="gmail.com"。
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    金鳞岂是池中物,一遇风云便化龙
    顶端 时间: 2006年01月04日 13:38 | 8 楼
    reload_cn

    头衔:CS高手 CS高手
    状态: 离线
    级别: CEC总版
    精华: 4
    发帖: 436
    威望: 72 点
    财富: 458 元
    在线时间:74(小时)
    注册时间:2005-09-21
    最后登录:2008-12-02

    这个我也不太清楚,但是我直接在用户名上输入: id@SERVERHOST(比如我在本机上安装了jabber服务器:reloadcn@127.0.0.1),这样也可以连
    顶端 时间: 2006年01月04日 21:40 | 9 楼
    goldwave

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 27
    威望: 11 点
    财富: 231 元
    在线时间:4(小时)
    注册时间:2006-02-07
    最后登录:2008-11-10

    做的不错,支持
    顶端 时间: 2006年03月17日 20:31 | 10 楼
    usamasara

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 23
    威望: 0 点
    财富: 229 元
    在线时间:13(小时)
    注册时间:2005-12-18
    最后登录:2008-09-05

    Quote:
    引用第8楼金鳞2006年01月04日 13:38发表的“”:
    我有个问题想问一下,如果想连接其他的Jabber服务器怎么办?在哪里设置?
    因为我看了一下org.eclipse.ecf.provider.xmpp.container.XMPPClientSOContainer这个类,
    他里面有个protected static final java.lang.String GOOGLE_SERVICENAME="gmail.com"。


    ECFConnextion.java

    if (google) {
       connection = new GoogleTalkConnection();
    } else if (serverPort == -1) {
      if (secure) {
       connection = new SSLXMPPConnection(serverName);
      } else {
       connection = new XMPPConnection(serverName);
      }
    } else {
      if (secure) {
       connection = new SSLXMPPConnection(serverName, serverPort);
      } else {
       connection = new XMPPConnection(serverName, serverPort);
      }
    }
    顶端 时间: 2006年04月10日 09:29 | 11 楼
    leonade

    状态: 离线
    级别: CEC程序员
    精华: 0
    发帖: 295
    威望: 12 点
    财富: 0 元
    在线时间:29(小时)
    注册时间:2006-04-07
    最后登录:2008-11-11

    好文阿。。。收藏了。。。
    这个功能过两天就用到了。。。
    顶端 时间: 2006年04月18日 09:06 | 12 楼
    scan

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 1
    威望: 1 点
    财富: 101 元
    在线时间:0(小时)
    注册时间:2006-05-23
    最后登录:2006-05-24

    我是来请教的 私有变量clientContainer所引用到的 XMPPClientSOContainer

    我在ECF包里面怎么找不到以致不能导入?
    顶端 时间: 2006年05月23日 20:41 | 13 楼
    yz_zcg

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 15
    威望: 1 点
    财富: 115 元
    在线时间:0(小时)
    注册时间:2006-05-31
    最后登录:2007-04-19

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    努力就会成功
    顶端 时间: 2006年06月01日 16:34 | 14 楼
    bjfullr

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 23
    威望: 11 点
    财富: 223 元
    在线时间:1(小时)
    注册时间:2005-09-29
    最后登录:2008-07-26

    文章不错,收藏了
    谢谢楼主
    顶端 时间: 2006年06月06日 21:44 | 15 楼
    血影蓝

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 21
    威望: 11 点
    财富: 223 元
    在线时间:1(小时)
    注册时间:2006-03-17
    最后登录:2006-09-16

    真是好东西
    最近想做一个IM,但还没有思路
    现在可以学习下了
    谢谢楼主
    顶端 时间: 2006年06月30日 20:56 | 16 楼
    lvye

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 4
    威望: 1 点
    财富: 105 元
    在线时间:0(小时)
    注册时间:2006-06-05
    最后登录:2007-08-17

    用ecf0.8.8,0.8.9运行该例,ecf里都没有
    import org.eclipse.ecf.core.ISharedObjectContainerListener;
    import org.eclipse.ecf.core.events.ISharedObjectContainerConnectedEvent;
    import org.eclipse.ecf.core.events.ISharedObjectContainerDisconnectedEvent;

    0.8.9里有.ISharedObjectContainerListener api 源代码里却没有.
    作者用的旧版本吧.但eclipse网站上没旧版本下载啊.
    有没有谁遇到这个问题?
    顶端 时间: 2006年07月20日 12:16 | 17 楼
    leehow

    状态: 离线
    级别: CEC高级程序员
    精华: 0
    发帖: 6
    威望: 11 点
    财富: 207 元
    在线时间:1(小时)
    注册时间:2006-02-19
    最后登录:2006-07-20

    顶端 时间: 2006年07月20日 17:21 | 18 楼
    pudong

    状态: 离线
    级别: CEC程序员
    精华: 0
    发帖: 38
    威望: 1 点
    财富: 46 元
    在线时间:0(小时)
    注册时间:2006-05-22
    最后登录:2007-05-22

    reload_cn者,牛人也
    顶端 时间: 2006年07月25日 14:27 | 19 楼
    « 1 23» Pages: ( 1/3 total )
    中国Eclipse社区 » 插件开发
    

    辽ICP备05021625号