24日目:ツイート検索アプリをつくる
今日はクリスマスイブです。いろんな過ごし方があるかと思いますが、今日は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() } }
実行結果
上記コードをコンパイル、実行すると次のようなウィンドウが表示されます。
テキスト入力欄に検索したい言葉を入力し、隣のSearchボタンをクリックします。すると次のような画面になります。
まとめと次回予告
今日はKotlinからTwitter4JとSwingを使ってツイート検索GUIアプリをつくりました。Java用ライブラリをKotlinから使う際には、NULL許容型と仲良くする必要があります。呼び出すメソッドが null を返し得るのかどうか、よくドキュメントを読んでから 演算子 !! を使用すべきです*4。SwingをKotlinフレンドリにしたパッケージ kotlin.swing に含まれるライブラリは、まだまだ提供されているクラスや関数は少ないですが、便利で面白い機能があります。
明日は待ちに待ったクリスマスです。当アドベントカレンダーも明日で最終回です。
日記
3連休はエンジョイしました。