JythonでつくるTwitterクライアント

プログラミング演習という授業で、swingを使ってGUIアプリを作れという課題が出されたところで、


「swing(とEventListener)を使ってさえいれば良いんだよね?」


というへりくつを思いつき、Jythonを使ってみたくなりました。
しかもちょうど最近2.5.0が出たばかりととてもいいタイミングです。

Jythonって何だ

もっともよく使われているPythonはCで書かれています。そこをCじゃなくてJavaで作ったPythonJythonです。
JythonではPythonのコードはJavaバイトコードに変換されて処理されるので、JavaVM上で動くプログラムがPythonで書ける、ということになります。

JythonTwitterClient


イベントリスナーの書き方くらいしかJavaとの違いはないですが、JavaのライブラリもPythonのモジュールも使えるという点はとても面白いです。


pythonのモジュールをJythonにインストールしたい場合は

jython setup.py install


でできます。かんたんですね。

'''
Created on 2009/06/22

@author: chkfj
'''
from javax.swing import *
from javax.swing.table import *
from javax.swing.event import *
from java.awt import *

import twitter,datetime,time

from settings import twitter_account

class TimelineSelectionListener(ListSelectionListener):
    def __init__(self,frame):
        self.frame=frame
    def valueChanged(self,event):
        self.frame.status_selected(event)

class TwitterClientFrame(JFrame):
    def __init__(self):
        self.api = twitter.Api(username=twitter_account.username, password=twitter_account.password)
        self.since = 0
        self.since_reply = 0
        
        self.setSize(480,640)
        self.setTitle("JythonTwitterClient - "+twitter_account.username)
        self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.setResizable(False)
        self.setLayout(FlowLayout())
        
        self.dm=DefaultTableModel([], ("ScreenName","Text","Date",))
        self.t = JTable(self.dm)
        self.t.setAutoCreateRowSorter(True)
        self.t.getSelectionModel().addListSelectionListener(TimelineSelectionListener(self))
        
        self.dm_replies=DefaultTableModel([], ("ScreenName", "Text", "Date",))
        self.replies_table = JTable(self.dm_replies)
        self.replies_table.setAutoCreateRowSorter(True)
        

        self.input = JTextField(42)
        self.add(self.input)  
        self.button = JButton("Post",actionPerformed=self.post_and_update)
        self.add(self.button)
        
        self.statusview = JTextArea("Twitter",3,42)
        self.statusview.setLineWrap(True)
        statuspanel = JPanel()
        statuspanel.setSize(Dimension(self.width,40))
        statuspanel.add(self.statusview)
        self.add(statuspanel)
        
        self.tab = JTabbedPane(JTabbedPane.TOP)
        
        s_ft=JScrollPane(self.t)
        s_ft.setPreferredSize(Dimension(self.width-10,500))
        s_replies=JScrollPane(self.replies_table)
        s_replies.setPreferredSize(Dimension(self.width-10, 500))
        self.tab.addTab("Friends", s_ft)
        self.tab.addTab("Replies", s_replies)
        self.add(self.tab)
        self.show()
        
    def update_table(self):
        try:
            timeline = self.api.GetFriendsTimeline()
            timeline.reverse()
        except:
            timeline=[]
        try:
            replies = self.api.GetReplies()
            replies.reverse()
        except:
            replies = []
            
        for t in timeline:
            if self.since >= t.id:continue
            self.dm.addRow([t.user.screen_name, t.text, datetime.datetime(*time.localtime(t.created_at_in_seconds)[:-3]).isoformat().replace(datetime.datetime.now().strftime("%Y-%m-%dT"),"") ])
        for r in replies:
            if self.since_reply >= r.id:continue
            self.dm_replies.addRow([r.user.screen_name, r.text, datetime.datetime(*time.localtime(r.created_at_in_seconds)[:-3]).isoformat().replace(datetime.datetime.now().strftime("%Y-%m-%dT"),"") ])
        self.since=long(timeline[-1].id)
        self.since_reply=long(replies[-1].id)
    
    def post_and_update(self,event):
        if self.input.text:
            self.api.PostUpdate(self.input.text)
            self.input.text=""
        self.update_table()
    
    def status_selected(self,event):
        index=self.t.getSelectedRow()
        self.statusview.text = self.t.getValueAt(index, 0)+" : "+self.t.getValueAt(index,1)

def main():
    f=TwitterClientFrame()
    f.update_table()
    
if __name__=='__main__':
    main()