読者です 読者をやめる 読者になる 読者になる

Kotlin Advent Calendar 2012 (全部俺)

JavaプログラマのためのKotlin入門

24日目:ツイート検索アプリをつくる

f:id:ngsw_taro:20121222110447j:plain

今日はクリスマスイブです。いろんな過ごし方があるかと思いますが、今日はKotlinでアプリを作って遊びましょう。

ツイート検索アプリをつくる

本日のタイトルのとおり、ツイート検索アプリをつくります!と言っても、100行もしない超簡単なアプリです。指定された言葉を含むツイートを検索して、ヒットしたツイートを表示するだけのアプリです。

ライブラリの用意

今回は2種類のライブラリを使います。まずツイートを検索、取得するためのライブラリとして@yusukeさんが開発、提供なさっているTwitter4Jです。そしてもう1つが、Swing*1をKotlinフレンドリにしたライブラリです。

Twitter4Jをこちらのサイトからダウンロードします*2。今回はtwitter4j-3.0.2.zipというファイルをダウンロードしました。twitter4j-core-3.0.2.jarというファイルにパスを通せばTwitter用ライブラリの準備は完了です。

次にKotlin向けSwingライブラリです。これはおそらくKotlin標準ライブラリという位置付けだと思いますが、現時点ではコンパイラと同梱されているライブラリには含まれていません。試したい方はGithubから手に入れてください*3

ツイート検索をする関数をつくる

まず最初に指定した言葉を含むツイートを検索する関数をつくりましょう。実行するにはTwitter連動アプリとしてTwitterアプリ登録し、与えられた各種キーを設定ファイルに書き出す必要があります。詳しくはTwitter APIについてぐぐってください。今回はTwitter4Jを使うのでtwitter4j.propertiesというファイルにその情報を記載する方法を採りました。

次にコードを書きます。

private fun searchTweets(keyword: String): List<Status> {
    val twitter = TwitterFactory().getInstance()
    val result = twitter?.search(Query(keyword))
    return result?.getTweets() ?: Collections.emptyList()
}

説明が不要なくらいに簡単な関数になりました。強いて説明するならば、Javaコードにおける参照型はKotlinで扱う際にNULL許容型になるので、演算子 !! や ?: を使用してNULL許容型との折り合いをつけています。

GUI部品をつくる

今回はSwingアプリということでJava標準ライブラリパッケージ javax.swing をKotlinフレンドリにした kotlin.swing というパッケージを使用しました。特徴はコンポーネント等を宣言的に定義できることと、イベント駆動をするようなボタンなどに対してコールバック関数を関数リテラルとして渡すことができるという点です。

全体のソース

ひとつひとつ言葉で説明するよりコードをご覧いただいた方がわかりやすいと思いますので、今回つくったツイート検索アプリの全体のコードを示します。

import java.awt.BorderLayout
import java.awt.Font
import java.util.Collections
import javax.swing.JFrame
import javax.swing.JScrollPane
import javax.swing.JTextArea
import javax.swing.JTextField
import javax.swing.SwingUtilities
import javax.swing.text.JTextComponent
import kotlin.swing.borderPanel
import kotlin.swing.button
import kotlin.swing.frame
import twitter4j.Query
import twitter4j.Status
import twitter4j.TwitterFactory

private fun searchTweets(keyword: String): List<Status> {
  val twitter = TwitterFactory().getInstance()
  val result = twitter?.search(Query(keyword))
  return result?.getTweets() ?: Collections.emptyList()
}

/* 拡張関数のように拡張プロパティを定義して
 * setText, getText をラップする
 */
private var JTextComponent.text: String
  get() = getText()!!
  set (value) = setText(value)

private fun createAndShowGUI() {
  /* JFrameのファクトリ関数。
   * 2つ目の引数として初期化用の関数リテラルを渡せる。
   */
  frame("Tweet Searcher") {
    setSize(400, 400)
    setLocationRelativeTo(null)
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)

    val tweetArea = JTextArea()
    tweetArea.setLineWrap(true);
    tweetArea.setEditable(false);
    tweetArea.setFont(Font(null, Font.PLAIN, 20));

    val searchField = JTextField()
    
    /* JButtonのファクトリ関数。
     * 2つ目の引数としてボタン押下時のコールバック関数を渡せる。
     */
    val searchButton = button("Search") {
      val strBuilder = StringBuilder()
      for(status in searchTweets(searchField.text)) {
        if(status != null) {
          strBuilder.append("■")
          strBuilder.append(status.getText())
          strBuilder.append(
            " [${status.getUser()?.getScreenName()}]")
          strBuilder.append("\n\n")
        }
      }

      tweetArea.text = strBuilder.toString()!!
    }

    add(
      borderPanel {
        add(
          borderPanel {
            add(searchField, BorderLayout.CENTER)
            add(searchButton, BorderLayout.EAST)
          },
          BorderLayout.NORTH
        )
        add(JScrollPane(tweetArea), BorderLayout.CENTER)
      }
    )
  }.setVisible(true)
}

/* SwingUtilities.invokeLaterへ処理を委譲する。
 * 関数リテラルを受け取り、Runnableオブジェクトでラップする。
 * invokeLaterをKotlinらしい形に変え、
 * 可読性/記述性を高める狙い。
 */
private fun invokeSwingApp(invoker : () -> Unit) {
  SwingUtilities.invokeLater(object : Runnable {
    override fun run() {
      invoker()
    }
  });
}

fun main(args : Array) {
  invokeSwingApp {
    createAndShowGUI()
  }
}

実行結果

上記コードをコンパイル、実行すると次のようなウィンドウが表示されます。

f:id:ngsw_taro:20121224211354p:plain

テキスト入力欄に検索したい言葉を入力し、隣のSearchボタンをクリックします。すると次のような画面になります。

f:id:ngsw_taro:20121224211456p:plain

まとめと次回予告

今日はKotlinからTwitter4JとSwingを使ってツイート検索GUIアプリをつくりました。Java用ライブラリをKotlinから使う際には、NULL許容型と仲良くする必要があります。呼び出すメソッドが null を返し得るのかどうか、よくドキュメントを読んでから 演算子 !! を使用すべきです*4。SwingをKotlinフレンドリにしたパッケージ kotlin.swing に含まれるライブラリは、まだまだ提供されているクラスや関数は少ないですが、便利で面白い機能があります。

明日は待ちに待ったクリスマスです。当アドベントカレンダーも明日で最終回です。

日記

3連休はエンジョイしました。

*1:Java標準ライブラリに含まれているGUIツールキットです。

*2:Mavenを使う場合は簡単に利用できます。詳細はTwitter4Jのサイトをご覧ください。

*3:私が試した時点では、このライブラリ内にいくつかの構文エラーがあったので注意してください。

*4:KotlinでNullPointerExceptionを投げる危険性を持つ演算子。詳細は16日目の記事を参照してください。