HOME | 2. widget を配置しよう | Python | 4. タイマーにボタンをつけよう | download | 書き込む |
この章では図1に示すようなアラームクロックをラベルだけで作ってみましょう。 このアラームはマウスの左ボタンで Start/Stop し、右ボタンで Reset します。
まず、Label widget の作成方法、イメージの貼り付け方を説明してから、 イベントによるラベルの変化のさせ方を説明します。
Tk.Label(master, **options)最初の引数で親 widget を指定し、キーワード引数を続けます。
属性 | 説明 |
---|---|
anchor | テキストを配置する位置を指定します。デフォルトは Tk.CENTER |
bg or background | 背景色を指定します。 |
bitmap | 表示する bitmap を指定します。 |
bd or borderwidth | 縁の幅を指定します。デフォルトは 2. |
cursor | カーソルの形を指定します。 |
font | テキストを表示する際のフォントを指定します。 |
fg or foreground | フォントの色、または bitmap の色を指定します。 |
height | ラベルの高さを行数で指定します。pixel 単位でないことに注意してください。 |
image | ラベルに貼る image を指定します。 |
justify | テキストが複数行にわたる場合、左寄せ、右寄せ、中央寄せを指定します。 |
padx | 縁とテキストとの間の横の余白。 |
pady | 縁とテキストとの間の縦の余白。 |
relief | ヘリの形 |
takefocus | 普通は Label には foculs はない。もし、focus を持ってきたければ、takefocus を 1 にする。 |
text | 表示する文字列 |
textvariable | StringVar を指定。変化する文字列を表示するとき用いる。 |
underline | (0 から数え始めて) n 番目の文字にアンダーラインをつける。デフォルトは -1. |
width | Label の幅、文字数単位。pixel 単位ではない。 |
wraplength | 改行幅 |
[code 1](rhello.py)
01: #! /usr/bin/env python 02: 03: import Tkinter as Tk 04: import random as R 05: 06: 07: class Label(Tk.Label): 08: def __init__(self, master=None): 09: Tk.Label.__init__(self, master, text='Hello world!', font=('Helvetica', '24', 'bold')) 10: self.bind_all('<1>', self.bg_change) 11: 12: def bg_change(self, event): 13: r = R.randint(0,255) 14: g = R.randint(0,255) 15: b = R.randint(0,255) 16: self.configure(bg='#%02X%02X%02X' % (r, g, b)) 17: 18: if __name__ == '__main__': 19: l = Label() 20: l.pack() 21: l.mainloop()このスクリプトの重要部分は 10 行目のイベントと関数を結びつける部分と、 16 行目の widget の属性を変化させる部分です。
10 行目が widget と Event を結びつけるメソッドです。 マウス左ボタンクリックは '<1>' と表されます。 イベントの記法については Tkinter reference: 24.2. Event sequences を見てください。
bind または bind_all メソッドの 最初の引数はイベントの種類で、2番目の引数はその Event が発生したときに呼び出される関数へのポインターです。 呼び出される関数は2引数の関数で、 最初の引数はインスタンス変数にアクセスするための self, 2番目の引数は event です。event は種種の属性を持っています。 event の属性については Tkinter reference: 24.6. Writing your handler を見てください。
16 行目の configure メソッドで widget の属性を変化させることができます。 ここでは背景色をランダムに変更しています。色の指定は名前による指定のほかに '#RGB' の形式で 指定できます。それぞれの色は 16 進法で表した 4, 8, あるいは 12 bit の正の整数です。
w.after(n, func)このメソッドは2つの引数をとり、2番目の引数は、 動作を定義した関数へのポインター(func)、最初の引数はミリ秒 (n) で、n ミリ秒後に finc を呼び出します。func が再帰的に func を呼び出すようにすると動作を継続させることができます。
[code 2] に例を示します。これは、左ボタンクリックするとHello World の温度が上がっていき、 その色がだんだん変化していきます。温度は 1000 K から 8000 K まで1秒間に 500 K の割合で変化します。
[code 2](thello.py)
01: #! /usr/bin/env python 02: 03: import Tkinter as Tk 04: import bbr as B 05: 06: class Frame(Tk.Frame): 07: def __init__(self, master=None): 08: Tk.Frame.__init__(self, master) 09: self.label=Tk.Label(self, text='click me!', width=32, height=2, \ font=('Helvetica', '8'), fg='white', bg='black') 10: self.label.pack(fill=Tk.BOTH) 11: self.bind_all('<1>', self.heating_start) 12: 13: def heating_start(self, event): 14: self.temp=1000 15: self.label.configure(width=12, height=1, text='Hello world!', font=('Helvetica', '24'), fg='black') 16: self.after(100, self.heating) 17: 18: def heating(self): 19: self.label.configure(fg=B.bbrcolor_rel(self.temp)) 20: self.temp += 50 21: if self.temp < 8000: 22: self.after(100, self.heating) 23: else: 24: self.label.configure(fg='black', bg='white') 25: 26: 27: if __name__ == '__main__': 28: f = Frame() 29: f.pack() 30: f.mainloop()まず、4 行目で温度と色とを関係づけるモジュール bbr (black body radiation) を import します。 (bbr は付録に つけておきますので、見てください。)次に、11 行目の
self.heating は self.temp から算出される色で、Hello world を表示し、その後、 self.temp を 50 K 上げ、self.temp が 8000 K になるまで、100 ミリ秒後に自分自身を呼び出します。 このように after メソッドと再帰関数を使うことによって widget を変化させることが できます。after メソッドは全ての widget に共通したメソッドなので、変化しうる widget 全てに 用いることができます。
[code 3](timer.py)
01: #! /usr/bin/env python 02: 03: """ 04: timer.py 05: 06: June 24, 2005 07: """ 08: 09: 10: import Tkinter as Tk 11: import sys 12: 13: BLUE = '#99CCFF' 14: YELLOW = '#FFCC00' 15: RED = '#FF00FF' 16: CLOCK = 'meza-bl-2.gif' 17: 18: class Frame(Tk.Frame): 19: 20: def __init__(self, master, min): 21: Tk.Frame.__init__(self, master) 22: 23: self.started = False 24: self.echo = Tk.StringVar() 25: self.min = min 26: self.echo.set('%02d:00' % (self.min)) 27: self.sec = 60 * self.min 28: 29: self.master.title('Alarm') 30: self.label = Tk.Label(self, text='Click to start', font=('Helvetica', '8')) 31: self.label.pack() 32: f = Tk.Frame(self, relief=Tk.RIDGE, bd=4) 33: f.pack(fill=Tk.BOTH, expand=1) 34: self.image= Tk.PhotoImage(file=CLOCK) 35: self.icon=Tk.Label(f, image=self.image, bg=BLUE) 36: self.icon.pack(side=Tk.LEFT) 37: display = Tk.Label(f, textvariable=self.echo, font=('Helvetica', '24'), 38: bg='white', width=5, anchor=Tk.E) 39: display.pack(side=Tk.LEFT) 40: self.bind_all('<1>', self.start_stop) 41: self.bind_all('<3>', self.reset) 42: 43: def start_stop(self, event): 44: if not self.started: 45: self.label.configure(text='Click to stop') 46: if 0< self.sec <= 20: 47: self.icon.configure(bg=YELLOW) 48: if 0 >= self.sec: 49: self.icon.configure(bg=RED) 50: self.after(1000, self.counting) 51: self.started = True 52: else: 53: self.label.configure(text='Click to start, RB to reset') 54: self.icon.configure(bg=BLUE) 55: self.started = False 56: 57: def counting(self): 58: if self.started: 59: self.sec -=1 60: self.echo.set('%02d:%02d' % (self.sec/60, self.sec%60)) 61: if self.sec == 20: 62: self.icon.configure(bg=YELLOW) 63: 64: if self.sec <= 0: 65: t= -1 * self.sec 66: self.icon.configure(bg=RED) 67: self.bell() 68: self.echo.set('-%02d:%02d' % (t/60, t%60)) 69: self.after(500, self.yellow) 70: 71: self.after(1000, self.counting) 72: 73: def yellow(self): 74: if self.started: 75: self.icon.configure(bg=YELLOW) 76: 77: 78: def reset(self, event): 79: if not self.started: 80: self.sec=60*self.min 81: self.echo.set('%02d:00' % (self.min)) 82: 83: 84: 85: if __name__ == '__main__': 86: min = len(sys.argv) > 1 and int(sys.argv[1]) or 3 87: f = Frame(None, min) 88: f.pack() 89: f.mainloop()
>python timer.py mとします。m は計測する時間(分)です。m が省略されると 3 分になります。 すると、図1で示した widget があらわれるので、それを左クリックします。すると、計測が始まります。 時計を止めるには動いている時計を左クリックし、リセットするには止まっている時計を右クリックします。
残り 20 秒を切ると時計アイコンの背景が黄色くなります。また、設定時間を過ぎるとアイコンの背景が赤−黄の 点滅をし、ベルを鳴らします。
今回は主にラベルを変化させる方法について述べました。実はこの方法は全ての widget でほとんど共通です。 従って、ここで述べた方法は他の widget でも応用が利くと思います。
次回は今回作ったアラームにボタンをつけてみます。
HOME | 2. widget を配置しよう | Python | 4. タイマーにボタンをつけよう | download | 書き込む |