Python:Tkを使って気軽にコンソールアプリ?

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コンソールのテスト")

でこんな風にみえる。

image

一番上に入力欄があって、その下に結果表示エリア。

Pythonの場合、stdoutはwriteというメソッド、stdinはreadlineというメソッドさえもっていればどんなオブジェクトでもオッケー。 なので単純にstdoutとstdinをTkのウィジットに置き換えてメインループに入り、別スレッドでメインの処理を実行してやっているだけ。

見栄えも生のDOSプロンプトよりはいいし、処理が終わってもウィンドウを閉じない限り結果を見ることができる。 プチ便利なので、はやくも自分で使いまくりです(笑

comments powered by Disqus