変化するテキストを表示するGUIクラス

yatt2008-08-22


ボードゲームNPCもどきやセルオートマトンのプログラムを書いていると、状態の遷移をCUIだけで確認するのが手間になってくる事がありませんか?できればGUIで綺麗に見たいけど、GUIプログラミングするのは面倒で退屈だし・・・そもそも元のプログラムよりGUIのコードの方が多くなってしまう残念な事になるしなあ・・という。そういう人向けの、というか自分向けのGUIクラス。一定時間ごとにコールバック関数を呼び出してLabelオブジェクトのテキスト属性としてダンプします。1、2次元のセルオートマトンと相性が良さげ。

使い方: こんな感じ

import time
a = TextPrinter(None, "title")
a.mainloop(lambda: a.getText().set(str(time.time())), 1.0)
#! /bin/env python
# -*- coding: utf-8 -*-
# textPrinter.py

import Tkinter as tk
import thread
import time

class TextPrinter(tk.Frame):
    def __init__(self, master=None, title="tk", font=("courier","18")):
        tk.Frame.__init__(self, master)
        self.master.title(title)

        # 変化する文字列を扱うStringVarオブジェクト
        self.text = tk.StringVar()
        self.text.set("")

        # テキストを表示させるLabelオブジェクト
        self.label = tk.Label(textvariable=self.text, font=font)
        self.label.pack()

    def getText(self):
        return self.text
    
    def mainloop(self, callback=lambda: True, interval=1.0):
        # interval秒毎にコールバック関数を実行する。
        # コールバック関数中でgetTextを使ってStringVar
        # オブジェクトのテキストを変更すれば期待した結果
        # が得られる
        def interval_callback():
            while True:
                callback()
                time.sleep(interval)
        thread.start_new_thread(interval_callback, ())
        tk.Frame.mainloop(self)
# -----------------------------------
# -----------------------------------


s = "@--------------------"
printer = TextPrinter(None, "this is title string")
def test():
    # @がくるくる
    def f():
        global s
        s = s[1:]+s[0]
        printer.getText().set(s)
    printer.mainloop(f, 0.02)
    
def test2():
    # 時間を表示
    printer.mainloop(lambda: printer.getText().set(str(time.time())), 1.0)

def asepTest(length, nnode, interval=0.08):
    # 7/5のエントリで書いたasepでのテスト
    import random
    import asep2
    asep = asep2.AsepField(length)
    for i in range(nnode):
        lst = [x for x in range(len(asep)) if asep[x].state() is False]
        idx = random.choice(lst)
        asep[idx].flip()
    def callback():
        t = "".join([str(x) for x in asep])
        printer.getText().set(t)
        asep.update()
    printer.mainloop(callback, interval)
        
def main():
    #asepTest(40, 20, 0.2)
    #test()
    test2()
    
if __name__ == '__main__':
    main()

このファイルと同じディレクトリに7月5日のエントリのasepのプログラムを"asep2.py"で保存するとasepTest()関数が使えるようになります。