Windowsの小物はほぼPythonで作っているわけですが。
WindowsにPythonをインストーラーを使ってインストールすると*.pyにデフォルトだとpython.exeを関連付けしてくれます。 これは非プログラマな人にプログラムを渡すとき非常に便利で、とりあえずPythonをインストールして、このファイルをダブルクリックしろ、というだけでオッケー。exe化して無駄な容量を食わなくても大丈夫なのです。
んで、作るのはだいたいコンソールで実行するもの。 これがダブルクリックで実行できるのはいいんですが、当然、プログラムが終了するとウインドウ(DOSプロンプト)が閉じちゃうから結果が見れない。 いちいちDOSプロンプトから実行するのもめんどくさい。しかも見た目的に非プログラマにはいかつい。
なんとかならないかなー、と思ってTkを使ってコンソールアプリを作るためのライブラリを作ってみた。
# vim: fileencoding=utf-8
from Tkinter import *
from ScrolledText import ScrolledText
import sys
import thread
import time
class GUIConsole(Frame):
def init(self):
self.init_input()
self.init_output()
def init_input(self):
self.input_var = StringVar()
self.input = Entry(self, width=100, textvariable=self.input_var)
self.input.pack(side=TOP)
self.input.bind('<Return>', self.input_enter)
self.input_var.readline = self.readline
sys.stdin = self.input_var
def init_output(self):
self.out = ScrolledText(self, width=100, height=30)
self.out.pack(side=TOP)
self.out.write = self.write
sys.stdout = self.out
def write(self, str):
self.out.insert(END, str)
time.sleep(0.0001)
self.out.yview_scroll(str.count("\n") + 1, "units")
def readline(self, size=None):
self.input.focus()
self.input_entered = False
while True:
time.sleep(0.5)
if self.input_entered == True:
break
result = self.input_var.get()
self.input_var.set("")
return result
def input_enter(self, event):
self.input_entered = True
def __init__(self, title, master=None):
self.input_entered = False
Frame.__init__(self, master)
self.pack()
self.master.title(title)
self.init()
def start(main_func, title="Python") :
app = GUIConsole(title)
thread.start_new_thread(main_func, ())
app.mainloop()
使い方はこんなかんじ。
import guiconsole
def main():
while True:
var = raw_input()
print var
guiconsole.start(main, "GUIコンソールのテスト")
でこんな風にみえる。
一番上に入力欄があって、その下に結果表示エリア。
Pythonの場合、stdoutはwriteというメソッド、stdinはreadlineというメソッドさえもっていればどんなオブジェクトでもオッケー。 なので単純にstdoutとstdinをTkのウィジットに置き換えてメインループに入り、別スレッドでメインの処理を実行してやっているだけ。
見栄えも生のDOSプロンプトよりはいいし、処理が終わってもウィンドウを閉じない限り結果を見ることができる。 プチ便利なので、はやくも自分で使いまくりです(笑