为 Twitter 创建图形客户端

在本教程中,您将使用 NetBeans IDE 创建一个基于 REST 的简单图形化客户端,通过该客户端可以显示 Twitter 好友时间线消息,以及查看和更新 Twitter 状态。该应用程序将使用 Swing 以及 NetBeans IDE 对 Twitter 的 SaaS 操作的支持。

显示 Twitter 消息的正在运行的客户端

如果您没有 Twitter 帐户,请先转至 twitter.com 并创建一个帐户,然后再继续学习本教程。

我们提供了此应用程序的完整样例以供下载。单击此处可以下载该样例。

目录

此页上的内容适用于 NetBeans IDE 6.9-7.1

要学完本教程,您需要具备以下软件和资源。

软件或资源 要求的版本
NetBeans IDE Java EE 下载包
Java 开发工具包 (JDK) 版本 6 或版本 7
Twitter 帐户的用户名和口令

设计 JFrame

在此步骤中,您将创建一些 GUI 元素,这些元素将用来显示 Twitter 好友时间线、用户图标以及读取和更新状态的位置。所有 GUI 元素都包装在 JFrame 中。您不必完全按照此部分中的所述布置 GUI 元素。该布局只是一个建议。例如,您可以添加更多功能。但是,您需要至少创建本教程中提及的所有元素。

设计 JFrame:

  1. 选择 "File"(文件)> "New Project"(新建项目)。此时将打开新建项目向导。选择 "Java" 类别,然后选择 "Java Application"(Java 应用程序)项目。单击 "Next"(下一步)。
  2. 将该项目命名为 TwitterSwingClient。选择一个项目位置。取消选中 Create Main Class(创建主类)。(JFrame 将会成为主类。)单击 "Finish"(完成)。
    显示用于创建 TwitterSwingClient 项目的字段的新建项目向导
  3. IDE 将创建 TwitterSwingClient 项目,该项目将显示在 "Projects"(项目)窗口中。右键单击 "TwitterSwingClient" 项目节点,然后选择 "New"(新建)> "JFrame Form"(JFrame 窗体),或者选择 "New"(新建)> "Other"(其他)> "Swing GUI Forms"(Swing GUI 窗体)> "JFrame Form"(JFrame 窗体)。此时将打开新建 JFrame 窗体向导。
  4. 将该窗体命名为 TwitterJFrame 并为其创建一个名为 twitterclient 的包。单击 "Finish"(完成)。
    显示用于创建 TwitterJFrame 的新建 JFrame 窗体向导
  5. IDE 将在编辑器的 "Design"(设计)视图中打开 TwitterJFrame。这里提供了一个包含所有 Swing 组件的组件面板,您可以将这些组件拖放至 JFrame 中。
    编辑器设计视图中的 Twitter JFrame
  6. 在 "Palette"(组件面板)中的 "Swing Controls"(Swing 控件)下,单击 "Button"(按钮)图标。将其拖放至 JFrame 的右下角。请注意,该按钮显示为 jButton1,这是此 JButton 对象的名称。
    显示新添加的 jButton1 的 JFrame
  7. 右键单击 "jButton1",然后从上下文菜单中选择 "Edit Text"(编辑文本)。将其显示文本更改为 "Update"。
  8. 将一个标签 (jLabel1) 拖放至 JFrame 的左下角。将其显示文本更改为 "Icon"。在此标签中将显示用户图标。
  9. 将一个文本字段 (jTextField1) 拖放至标签和按钮之间。将其显示文本更改为 "Status"。单击该文本字段的右边框,然后将其朝按钮拉伸。此时会出现蓝色的基准线,指示到按钮的建议距离。
  10. 右键单击 "jLabel1",然后从上下文菜单中选择 "Properties"(属性)。“jLabel1 属性”对话框打开。设置 "labelFor" 属性指向 jTextField1。(这样可以提高可访问性。)
  11. 找到最大大小、最小大小以及首选大小所对应的属性。将所有这些属性设置为 "[48,48]",以与 Twitter 图标 48 X 48 像素的尺寸相匹配。
    Twitter JFrame 中的 jLabel 1 的属性,显示最大值、最小值,并且其首选大小设置为 48、48
  12. 将一个滚动窗格拖放至 JFrame 的上半部分。拖动其边框,将其扩展至填充文本字段和按钮上方的大部分或全部空白区域。(如果希望在以后添加更多功能,如样例中的菜单,则可以留出一个旁注。)
  13. 将一个列表拖放至滚动窗格中。将显示一个项目样例列表。保存 TwitterJFrame。JFrame 应如下图所示:
    设计视图中的 Twitter JFrame,带有所有基本 GUI 元素

现在,您已具有用于 Swing 客户端的所有基本 GUI 组件。接下来,该添加第一个 Twitter SaaS(Software as a Service,服务型软件)操作。

显示用户状态

在此部分,您将创建一个新方法,并向此方法中添加 Twitter getUserTimeline 操作。getUserTimeline 操作可获取您的用户图标和当前状态。然后,您将向该方法中添加代码,以在 jLabel1 和 jTextField 中分别显示您的图标和状态。最后,您将向 JFrame 的构造函数中添加一行代码来初始化该方法。

显示用户状态:

  1. 切换至 TwitterJFrame 的 "Source"(源)视图。
  2. 按 Alt-Insert 组合键,或右键单击并从上下文菜单中选择 "Insert Code"(插入代码)。此时会打开一个用于插入代码的菜单。
    用于在 initUserInfo 方法中插入代码的菜单
  3. 单击 "Generate REST Client"(生成 REST 客户端)。"Available REST Resources"(可用的 REST 资源)对话框打开。
  4. 选择 "IDE Registered"(IDE 中的已注册服务)单选按钮,然后单击 "Browse"(浏览)。导航至 "Twitter" > "Twitter OAuth" > "[statuses]" > "[user_timeline.{format}]"。单击 "OK"(确定)。
    带有 Web 服务树的
  5. "Available REST Resources"(可用的 REST 资源)对话框现在会显示所选的 Twitter OAuth user_timeline 资源、对应的类名和 OAuth 验证类型。单击 "OK"(确定)。
    已填充的
  6. 此时会打开一个对话框,询问您是否希望通过 WADL 文件中的 XML 方案引用来生成 Java 对象。单击 "Yes"(是)。
  7. 在 TwitterJFrame 类的末尾,IDE 会生成一个名为 Twitter_OAuth_user_timeline__format_JerseyClient 的内部类。

    该内部类很复杂,其中包含以下字段、方法和内部类:

    • CONSUMER_KEY:使用者键值字符串
    • CONSUMER_SECRET:使用者密钥字符串
    • initOAuth():用于 OAuh 初始化的方法
    • getUserTimeline():对应于 HTTP 方法 getUserTimeline(来自 REST 资源)的方法
    • makeOAuthRequestUnique():对于一个会话中的多个 API 调用非常有用
    • login:用于登录 Twitter 应用程序(强制授权)。此方法会调用另外两个生成的方法:getOAuthAccessTokengetOAuthRequestToken

    以下是 "Navigator"(导航器)窗口中显示的类结构。

    显示 Twitter_OAuth_user_timeline__format_JerseyClient 类的
  8. 在内部 Twitter_OAuth_user_timeline__format_JerseyClient 类正上方的 TwitterJFrame 中,插入以下代码行。此代码会创建一个名为 client 的变量,代表内部类的实例。
    private Twitter_OAuth_user_timeline__format_JerseyClient client;
    在内部类正上方显示客户端变量的代码片段
  9. 找到 TwitterJFrame 中的 main 方法。在此方法上方,创建一个名为 initUserInfo 的新方法,用于引发 MalformedURLException 和 IOException。
    private void initUserInfo() throws MalformedURLException, IOException {
    
    
    
    }
  10. 将以下代码插入 initUserInfo 的方法主体。代码中的注释说明了代码的作用。
    private void initUserInfo() throws MalformedURLException, IOException {
    
    //Create an instance of the internal service class client = new Twitter_OAuth_user_timeline__format_JerseyClient("xml");
    //Log in, get tokens, and append the tokens to the consumer and secret //keys client.login(); client.initOAuth();
    //Call getUserTimeline, get a list of statuses, pass the most recent //status as a StatusType object, and display the text of that object //in the JTextField Statuses statuses = client.getUserTimeline(Statuses.class, null, null, null, "1"); StatusType st = statuses.getStatus().get(0); jTextField1.setText(st.getText().trim());
    //Get a UserType object from the StatusType object, get the URL of that //user's icon, and display that icon in the JLabel UserType user = st.getUser(); String iconSrc = user.getProfileImageUrl(); URL iconUrl = new URL(iconSrc); ImageIcon icon = new ImageIcon(iconUrl, user.getScreenName()); jLabel1.setIcon(icon); }
  11. 打开 "Fix Imports"(修复导入)对话框(按 Ctrl/⌘-Shift-I 组合键,或从上下文菜单中进行选择)。在该对话框中,选择 twitter.twitteroauth.twitterresponse.StatusType,而不是默认的 Java StatusType 类。
    完成 initUserInfo 方法后的
  12. 将 try/catch 块添加到 TwitterJForm 构造函数中,以在应用程序运行时调用 initUserInfo。在添加 try/catch 块之后进行修复导入。
    public TwitterJFrame() {
        initComponents();
    
        try {
            initUserInfo();
        } catch (IOException ex) {
            Logger.getLogger(TwitterJFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
     }

在您从 Twitter 获取 OAuth 键值之后,就可以运行该项目了。右键单击该项目节点,然后从上下文菜单中选择 "Run"(运行)。将打开一个应用程序,显示您的用户图标和状态。

从 Twitter 获取 OAuth 键值

为了使 Java 应用程序能够访问 Twitter 数据,您需要从 Twitter 获取 CUSTOMER 和 CUSTOMER_SECRET 键值,以及验证字符串。Twitter 使用 OAuth 授权,而 OAuth 授权需要这些键值。但是,预计 OAuth 将设置为可由服务器上的 Web 应用程序调用。为了获取授权码,您要注册“伪”Web 应用程序。

从 Twitter 获取 OAuth 键值:

  1. 打开浏览器。转至 "Twitter" > "Applications"(应用程序)页面,然后单击 Register a new application(注册新应用程序)。您需要登录 Twitter 帐户。如果您具有多个帐户,请确保您登录到正确的帐户。
  2. Application Name(应用程序名称)文本字段中键入 NB User Timeline Application
  3. Description(描述)字段中键入描述。此字段为必填字段。您可以键入一些类似 "Java application created in NetBeans IDE calling the user_timeline operation" 的内容。
  4. Application Website(应用程序网站)字段中键入任意 URL。
  5. Application Type(应用程序类型)选项中,选择 "Client"(客户端)单选按钮。
  6. Default Access Type(默认访问类型)部分,选择 "Read & Write"(读和写)按钮。

    注:确保您选择的是 "Read & Write"(读和写)。尽管您可以稍后返回来编辑您的设置,但这似乎不会影响您的应用程序访问权限。

  7. 将其他选项保留为默认设置,然后按 "Save"(保存)。此时会打开浏览器页面,其中包含您已注册的应用程序的详细信息。重要的详细信息是 Consumer key(使用者键值)和 Consumer secret(使用者密钥)。
  8. 从浏览器中复制 "Consumer key"(使用者键值)。在 IDE 中,找到其中设置 CONSUMER_KEY 的行。在引号之间粘贴使用者键值。
    显示 CONSUMER_KEY 和 CONSUMER_SECRET 位置的 TwitterClient
  9. 将浏览器中的使用者密钥键值复制并粘贴到 TwitterSwingClient。保存所做的更改。

运行项目

既然您已具有使用者键值和使用者密钥键值,就可以开始运行项目了。该应用程序会调用 Twitter,此过程将打开浏览器窗口以使应用程序能够访问数据。

运行项目:

  1. 如果 TwitterSwingClient 是您的主项目,请按 F6。否则,请右键单击 "TwitterSwingClient" 项目节点,然后从上下文菜单中选择 "Run"(运行)。
  2. 此时会打开浏览器窗口,询问您是否希望允许已注册的应用程序访问 Twitter 数据。单击 "Allow"(允许)。
  3. 浏览器窗口会更新为显示个人识别码的新窗口。复制此个人识别码。
  4. 在 IDE 中,输出窗口会显示一个请求,要求您键入 oauth_verifier 字符串。在冒号 : 后面粘贴个人识别码,然后按 Enter 键。
    IDE 中要求提供验证器字符串的
  5. 此时会打开桌面客户端,显示最新的 Twitter 状态消息。
    显示用户图标和状态的正在运行的应用程序

调用多项服务

应用程序的最终设计需要调用三项 Twitter 服务:user_timeline{format}(已经调用)、update{format} 和 friends_timeline{format}。对这些服务的调用需要共享一个登录名。为了使这些调用共享同一个登录名,它们必须在同一个客户端类中。从一个客户端调用多项服务需要以下两个步骤:

  • 将多项服务添加到一个客户端类中。
  • 修改客户端类中的资源路径

添加服务并将调用合并到一个类中

在此部分中,您首先为其他服务添加客户端,然后将它们合并到一个常规客户端中。

添加多项服务:

  1. 按 Alt-Insert 组合键,然后选择 "Generate REST Client"(生成 REST 客户端)。
    用于在 initUserInfo 方法中插入代码的菜单
  2. 按照显示您的用户状态部分遵循的过程生成 REST 客户端,只是选择 "[statuses]" > "[update.{format}]" 服务。IDE 会生成内部类 Twitter_OAuth_update__format_JerseyClient,它类似于 Twitter_OAuth_user_timeline__format_JerseyClient 类。
    显示更新格式服务的
  3. 重复上文中的步骤 1 和 2 为 [friends_timeline.{format}] 服务添加客户端。
  4. 更改原始 Twitter_OAuth_user_timeline__format_JerseyClient 类的名称。您将生成此调用所有 3 项服务的常规客户端类。选择名称为 Twitter_OAuth_user_timeline__format_JerseyClient 的实例,然后按 Ctrl-R 组合键,或者右键单击并选择 "Refactor"(重构)> "Rename"(重命名)。“重命名类”对话框打开。键入新的名称 TwitterClient。
    带有新名称 TwitterClient 的
  5. 单击 "Refactor"(重构)。IDE 会替换类名的所有实例。
    类名已在多个位置更改
  6. 在 "Navigator"(导航器)窗口中,找到 Twitter_Oauth_friends_timeline__format_JerseyClient 类。在该类中,找到并双击 getFriendsTimeline 方法。
    显示 getPublicTimeline 方法的
  7. 编辑器中的光标会移动至 getFriendsTimeline 方法。剪切该方法(在下方重新生成)。
    public <T> T getFriendsTimeline(Class<T> responseType, String since, String since_id, String page, String count) throws UniformInterfaceException {
          String[] queryParamNames = new String[]{"since", "since_id", "page", "count"};
          String[] queryParamValues = new String[]{since, since_id, page, count};
          return webResource.queryParams(getQueryOrFormParams(queryParamNames, queryParamValues)).accept(javax.ws.rs.core.MediaType.TEXT_XML).get(responseType);
    }
  8. getFriendsTimeline 方法粘贴到 getUserTimeline 方法下的 TwitterClient 内部类中。
  9. updateStatus 方法从 Twitter_OAuth_update__format_JerseyClient 剪切并粘贴到 getFriendsTimeline 方法下的 TwitterClient 中。

修改资源路径

现在,所有 Twitter 服务调用都在一个客户端类中。但是,该客户端类中的资源路径的构造不正确。在 IDE 最初生成该类时,还生成了特定于 user_timeline 服务的资源路径。您需要修改该类,以使得在该类级别下,资源路径是通用的,并且特定路径由服务调用方法指定。

修改资源路径:

  1. 找到 TwitterClient 构造函数,并删除 String format 参数。
    从构造函数中删除参数之前和之后的视图
  2. 此时右旁注中会出现一个红色的错误线。单击该错误线,您会转至 initUserInfo 中实例化 TwitterClient 类的行。此行为 client = new TwitterClient("xml");。删除参数 "xml",因为 TwitterClient 构造函数不再使用该参数。该行现在为 client = new TwitterClient();。此时错误图标会消失。
  3. 返回到 TwitterClient 构造函数。("Navigator"(导航器)窗口可以帮助您完成。)找到以下行:
    String resourcePath = java.text.MessageFormat.format("statuses/user_timeline.{0}", new Object[]{format}); 

    此行为整个类设置 resourcePath。更改该行,以使 resourcePath 指向父 statuses 目录。该行现在如下所示:

    String resourcePath = "statuses";
  4. 导航至 getUserTimeline 方法。找到 return 行:
    return webResource.queryParams(getQueryOrFormParams(queryParamNames, queryParamValues))...;

    将路径信息(在下方的 boldface 中)附加到调用的开头。

    return webResource.path("user_timeline.xml").queryParams(getQueryOrFormParams(queryParamNames, queryParamValues)).accept(javax.ws.rs.core.MediaType.TEXT_XML).get(responseType);
  5. 导航至 getFriendsTimeline 方法。找到 return 行:
    return webResource.queryParams(getQueryOrFormParams(queryParamNames, queryParamValues)).accept(javax.ws.rs.core.MediaType.TEXT_XML).get(responseType);

    将路径信息附加到调用的开头。

    return webResource.path("friends_timeline.xml").queryParams(getQueryOrFormParams(queryParamNames, queryParamValues)).accept(javax.ws.rs.core.MediaType.TEXT_XML).get(responseType);
  6. 导航至 updateStatus 方法。找到 return 行:
    return webResource.type(javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED)...

    将路径信息附加到调用的开头。

    return webResource.path("update.xml").type(javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED).post(responseType, getQueryOrFormParams(formParamNames, formParamValues));
  7. 找到并注释掉 TwitterClient 的 setResourcePath 方法。该方法还没有被调用,但这是一个预防措施。
  8. 删除 Twitter_OAuth_update__format_JerseyClient 和 Twitter_Oauth_friends_timeline__format_JerseyClient 类。

您现在已经可以通过 JerseyClient 类获得所有三项服务。

重要信息:您要在上述过程中更改三种方法内的三个 return 语句。请确保更改所有三个语句!

添加更新状态操作

  1. 返回至 TwitterJFrame 的 "Design"(设计)视图。双击 JFrame 中的 "Update" 按钮。编辑器会切换回 "Source"(源)视图,并且光标位于 IDE 刚创建的 jButton1ActionPerformed 方法主体内。
    源视图中的 TwitterJFrame,光标位于新创建 jButton1ActionPerformed 方法的中间
  2. 按照如下方式填写 jButton1ActionPerformed 方法正文:

    注:当您更新您的状态时,该状态会以 UTF-8 编码形式显示,并且空格显示为 + 号或 %21 符号等。但是,如果未将文本字段内容转换为 UTF-8,则在状态消息中键入任何空格时,应用程序将失败,并显示“签名无效”!如果有任何人发现了解决此问题的方法,请使用教程底部的“反馈”链接与我们联系。

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        String rawStatus = jTextField1.getText().trim();
        String status = URLEncoder.encode(rawStatus, "UTF-8");
        client.makeOAuthRequestUnique();
        try {
        client.updateStatus(String.class, status, null);
        } catch(UniformInterfaceException ex) {
            System.out.println("Exception when calling updateStatus = " + ex.getResponse().getEntity(String.class));
        }
    
    }    

此代码从文本字段获取文本,并将其传递到 updateStatus 类。请注意对 makeOAuthRequestUnique 的调用。代码会调用此方法,因为在应用程序初始化时,就已经登录,并且由对 initUserInfo 中的 logininitOAuth 的调用进行了验证。makeOAuthRequestUnique 方法增加了现有的 OAuth 和时间戳参数,以确保每个请求都是唯一的。

注:并不完全清除此处调用 makeOAuthRequestUniqueinitOAuth 效果是否会更好。如果您遇到验证问题,请使用这两种形式进行试验。

另外请注意,对 updateStatus 的调用包装在 try/catch 块中。这样可以帮助您调试在调用 updateStatus 时可能发生的任何问题。

在 JFrame 中显示用户名和状态

现在,将应用程序设置为显示您的 Twitter 好友的用户名和状态。

  • 为了从 Twitter 获取用户名和状态,应用程序将在运行时调用 Twitter getFriendsTimeline 操作。要对此进行设置,请创建新的 run 方法,该方法将覆盖 main 中的 run 方法。将对 getFriendsTimeline 的调用插入此方法中。
  • 要使显示自动更新,请将包含 getFriendsTimeline 操作的 run 方法包装到 java.util.TimerTask 类中,该类每 75 秒执行一次 run 方法。
  • 应用程序将以列表中单元格的形式显示数据。您需要将数据传递到能够以列表中单元格的形式呈现的 GUI 组件中,同时还需要设置数据显示的格式。要实现此操作,请创建一个新 JPanel,以实现 javax.swing.ListCellRenderer。该 JPanel 返回一个 java.awt.Component 对象,其中包含传入 JLabel 的用户名和状态。此外,还需调整 JPanel 的格式。
  • 在 TwitterJFrame 中,设置 JList 以显示由 JPanel 返回的 Component 对象。

创建 TimerTask

要自动更新显示的 Twitter 好友时间线,请将执行代码包装到 TimerTask 中。首先编写一个 TimerTask 包装器,然后使用执行代码填充该包装器。否则,代码将出现许多错误警告。

创建 TimerTask:

  1. 在编辑器的 "Source"(源)视图中打开 TwitterJFrame。
  2. 找到类声明和构造函数。
    public class TwitterJFrame extends javax.swing.JFrame {
    
        /** Creates new form TwitterJFrame */
        public TwitterJFrame() {
            initComponents();
            try {
                initUserInfo();
            } catch (IOException ex) {
                Logger.getLogger(TwitterJFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
  3. 在构造函数方法主体的 initComponents(); 上面,实例化 java.util.Timer 类。参数将 Timer 线程命名为 "Twitter Updater",并且指定该线程不能以守护进程运行。
    public class TwitterJFrame extends javax.swing.JFrame {
    
        /** Creates new form TwitterJFrame */
        public TwitterJFrame() {
            Timer t = new Timer("Twitter Updater`", false);
            initComponents();
            try {
                initUserInfo();
            } catch (IOException ex) {
                Logger.getLogger(TwitterJFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
                        
  4. 在编辑器中的任意位置右键单击,然后从上下文菜单中选择 "Fix Imports"(修复导入),或者按 Ctrl/⌘-Shift-I 组合键。此时将打开一个对话框,您可以选择要导入的类。为 java.util.Timer 添加一个 import 语句。
  5. Timer 实例化下面,创建一个新 Timer.scheduleAtFixedRate 方法。该方法的参数包括一个 TimerTask 对象、该方法首次运行任务前的延迟及其运行任务的频率。将方法设置为在初次运行之前等待 30 秒,并且每 75 秒重新运行一次。(较长的初始延迟为您提供了登录的时间。)具体的代码如下所示(粗体显示的部分)。在放置执行代码的位置留有一个空行。请注意,必须为 java.util.TimerTask 添加一个 import 语句。
    public class TwitterJFrame extends javax.swing.JFrame {
    
        /** Creates new form TwitterJFrame */
        public TwitterJFrame() {
            Timer t = new Timer("Twitter Updater`", false);
            t.scheduleAtFixedRate(new TimerTask() {

    }, 30000, 75000);
    initComponents(); try { initUserInfo(); } catch (IOException ex) { Logger.getLogger(TwitterJFrame.class.getName()).log(Level.SEVERE, null, ex); } }

现在,已完成 TimerTask 包装器代码。接下来,您将添加执行代码。

使用 getFriendsTimeline 操作添加 run 方法

为了显示用户名和状态,应用程序将首先从 Twitter 获取该数据。Twitter SaaS 提供了用于获取用户名和状态的 getFriendsTimeline 操作。要在应用程序运行时执行 getFriendsTimeline 操作,该操作必须包含在 run 方法内。最后,因为应用程序将在 JList 中显示用户名和状态,所以应用程序需要将 getFriendsTimeline 的结果作为 DefaultListModel 对象的元素进行添加。

使用 getFriendsTimeline 操作添加 run 方法:

  1. 在 TwitterJFrame 构造函数上面,创建一个名为 statusesListModelDefaultListModel 对象。
    public class TwitterJFrame extends javax.swing.JFrame {
    
        private DefaultListModel statusesListModel = new DefaultListModel();
    
    /** Creates new form TwitterJFrame */ public TwitterJFrame() {
  2. 在编辑器中的任意位置右键单击,然后从上下文菜单中选择 "Fix Imports"(修复导入),或者按 Ctrl/⌘-Shift-I 组合键。此操作将为 DefaultListModel 添加一个 import 语句。
  3. TimerTask 对象的主体中,创建一个新 run 方法。使用 @Override 标注覆盖 main 中的 run 方法。
    public class TwitterJFrame extends javax.swing.JFrame {
    
        private DefaultListModel statuses = new DefaultListModel();

    /** Creates new form TwitterJFrame */ public TwitterJFrame() { Timer t = new Timer("Twitter Updater`", false);
    t.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run(){

    }

    }, 1500, 75000);
    initComponents(); try { initUserInfo(); } catch (IOException ex) { Logger.getLogger(TwitterJFrame.class.getName()).log(Level.SEVERE, null, ex); }
  4. 将以下代码插入 run 方法的主体。
    @Override
    public void run() {
        System.out.println("Timer Task is running");
        try {
            client.initOAuth();
            Statuses response = client.getFriendsTimeline(Statuses.class, null, null, null, "10");
            // Clear the list model so it does not replicate the contents from the last run
            statusesListModel.clear();
            // Create a Status Type object for every status in the Status list, and add an element
            // to the list model for every status type object
            for (final StatusType st : response.getStatus()) {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        statusesListModel.addElement(st);
                    }
                });
            }
        } catch (UniformInterfaceException ex) {
        System.out.println("Exception when calling getFriendsTimeline = " + ex.getResponse().getEntity(String.class));
        }
    }

现在,已完成从 Twitter 好友时间线获取状态的代码。接下来,您将编写一个新类,以返回 Component,其中包含在 GUI 组件中呈现的列表元素。

创建呈现组件的列表单元格

现在,您已具有可从 Twitter 好友时间线获取 Status 对象并为每个 Status 创建列表元素的代码。但是,无法在 JList 中显示这些原始列表元素。您需要将数据传递到 GUI 组件中。要实现此操作,请创建一个新 JPanel,以实现 javax.swing.ListCellRenderer。该 JPanel 返回一个 java.awt.Component 对象,其中包含传入 JLabel 的用户名和状态。您可以在 JPanel 中定制 JLabel 的外观。

添加呈现组件的列表单元格:

  1. 右键单击该项目的节点,然后选择 "New"(新建)> "JPanel Form"(JPanel 窗体)。此时将打开新建 JPanel 窗体向导。
  2. 将该 JPanel 命名为 Item,并将其放置在 twitterclient 包中。
    显示名为
  3. 单击 "Finish"(完成)。将在编辑器的 "Design"(设计)视图中打开 Item.java
  4. 将一个标签和一个文本窗格拖放至 JPanel 中。标签将显示用户名,而文本窗格将显示用户的状态消息。
  5. 调整标签和文本窗格的位置,以使其与希望的数据显示方式相匹配。在下图中,用户名位于左上角,而状态文本则位于紧随其下略微缩进的位置。在样例项目中,左上角显示数据,右下角显示用户名。应在 JPanel 中的文本窗格下面留出足够的空间,以便文本窗格在包含较长的文本时进行扩展。
    显示用户名和状态文本的 jlabel 的布局
  6. 右键单击 JLabel 元素,然后从上下文菜单中选择 "Properties"(属性)。在 "Properties"(属性)中,可以对字体、颜色、对齐方式以及其他属性进行更改。将 labelFor 属性设置为指向 jTextPane1。这样可以提高可访问性。尝试调整标签的属性直到您对外观满意为止。在下图中,前景属性中的字体颜色已被设置为蓝色。
    前景设置为蓝色的 JLabel 属性对话框
  7. 打开 JTextPane 的 "Properties"(属性)对话框,然后尝试调整其外观。
  8. 切换至 Item.java 的 "Source"(源)视图。找到 "Generated Code" 块并将其展开。此操作将显示设置 JLabel 和 JTextPane 的属性时由 IDE 生成的代码。

    在下图中,请注意对 JLabel1 所做的蓝色设置。您能看出对 JTextPane 设置了哪些属性吗?

    通过在设计视图中设置 JLabel 属性在 Item.java 中生成的代码
  9. 找到类声明,然后添加代码 implements ListCellRenderer
    public class Item extends javax.swing.JPanel implements ListCellRenderer {
  10. 按 Ctrl-Shift-I 组合键(在 MacOS 上按 ⌘-Shift-I 组合键)。此操作将为 javax.swing.ListCellRenderer 添加一个导入语句。此时会出现一个警告,指明需要实现所有抽象方法。
  11. 在生成的代码块和变量声明之间添加一些空行。向该空白区域中添加以下代码,以实现抽象方法 getListCellRendererComponent。(可以复制并粘贴该代码,也可以尝试使用代码完成生成该代码。)该代码将使用通过 twitteroauth StatusType 类获取的 Text、User 和 ScreenName 对象替换默认的标签文本 "username" 和 "text"。然后,该代码将返回一个包含这些新 JLabel 文本值的 Component 实例。
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) {
            StatusType st = (StatusType) value;
            jTextPane1.setText(st.getText());
            jLabel1.setText("<html>" + st.getUser().getScreenName() + "</html>");
            return this;
    }
  12. 按 Ctrl-Shift-I 组合键(在 MacOS 上按 ⌘-Shift-I 组合键)。此操作将为 StatusType 和 Component 类添加导入语句。选择 StatusType 的 twitteroauth 版本。保存 Item.java。

现在,您已具有一个 Item 类,该类返回其中包含在 JLabel 和 JTextPane 中显示的用户名和状态的 Component 对象。接下来,您将修改 TwitterJFrame 以使用此 Component。

在 TwitterJFrame 中显示 Component

为了显示在 Item.java 中创建的 Component 对象,TwitterJFrame 中的 JList 必须使用 Item.java 作为其单元格呈现器。

  1. 返回至 TwitterJFrame。在 "Design"(设计)视图中,选择 JList。单击鼠标右键,然后打开其 "Properties"(属性)。
    TwitterJFrame 中 JList 元素的属性对话框
  2. 选择 model 属性。按 Ctrl-空格组合键。将打开定制属性编辑器,其中显示了列表中所显示的默认文本。
    Jlist 定制属性编辑器
  3. 在 "Set jLlist1's model property using:"(使用以下内容设置 jList1 的 model 属性:)下拉菜单中,选择 "Custom Code"(定制代码)。将出现一个文本字段,可以在其中键入 jLabel1.setModel 的属性。在该字段中键入 statusesListModel,然后单击 "OK"(确定)。
    jList 定制属性编辑器,其中显示在定制代码编辑器中选定了 setModel(statuses)
  4. 在 "Properties"(属性)对话框中,选择 "cellRenderer",然后按 Ctrl-空格组合键。将打开定制属性编辑器。
  5. 在 "Set jList1's cellRenderer property using:"(使用以下内容设置 jList1 的 cellRenderer 属性:)下拉菜单中,选择 "Custom Code"(定制代码)。将出现一个文本字段,可以在其中键入 jList1.cellRenderer 的属性。键入 new Item(),然后单击 "OK"(确定)。
    显示选定新项的 JList 定制单元格呈现器属性编辑器

现在,已完成客户端应用程序!保存所有文件,然后运行该应用程序。(右键单击项目节点,然后选择 "Run"(运行)。)此时将打开该应用程序,其中显示一个时间线消息列表以及一个包含您自己状态的字段。

显示 Twitter 消息的正在运行的客户端

通过代理进行连接;

如果您是通过代理连接至 Internet 的,则需要同时对 IDE 和 TwitterSwingClient 项目进行配置以使用代理设置。

要配置 IDE,请打开 "Tools"(工具)> "Options"(选项)> "General"(常规)。找到 "Proxy Settings"(代理设置)部分。您可以选择使用无代理设置、使用系统代理设置或使用手动代理设置。IDE 将从默认的系统 Web 浏览器中获取系统代理设置。

对于 TwitterSwingClient 项目,需要指定 HTTP 协议处理程序使用的代理。Java SE 6 文档中对此进行了介绍。您需在传递给虚拟机的选项中指定代理。在 NetBeans IDE 中,这些选项是在 "Properties"(属性)对话框中设置的。

为 TwitterSwingClient 项目指定代理:

  1. 在 "Projects"(项目)窗口中,右键单击 "TwitterSwingClient" 项目节点,然后选择 "Properties"(属性)。"Properties"(属性)对话框打开。
  2. 在 "Categories"(类别)树下,选择 "Run"(运行)。将显示 "Run"(运行)属性。
  3. 在 "VM Options"(VM 选项)字段中,输入 -Dhttp.proxyHost=server -Dhttp.proxyPort=port。请将 "server" 和 "port" 分别替换为您的代理服务器的主机名和端口!

更多练习

下面是供您探讨的更多思路:

  • 更改 Twitter 用户图标(在浏览器中),然后重新运行客户端。是否会显示新图标?
  • 向 JFrame 中添加一个具有某些功能的工具栏。

另请参见

有关使用 NetBeans IDE 创建和使用 Web 服务以及设计 GUI 的更多信息,请参见以下资源:

要发送意见和建议、获得支持以及随时了解 NetBeans IDE Java EE 开发功能的最新开发情况,请加入 邮件列表

get support for the NetBeans

Support


By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2013, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo