Python(tkinter001: ラジオボタン, after他)
■tkinterのサンプルコードの改修(ラジオボタン、after追加)
もう少しtkinterを触ってみる。前回のサンプルコードに次の修正を入れる。
1.前回、グラフを画像ファイルに保存してからtkinterで参照したので、データで受け渡すようにする。
2.2次関数の定数a, b, cをランダムに決めるパターンを追加し、ラジオボタンで切りかえれるようにする。
3.tkinterのafterを使って、ランダムに決めるパターンが自動的に更新されるようにする。
では、まず1から。
前回は、matplotlibでグラフをプロットしてから「sample017.png」という名前のファイルに保存し、その後、tkinterのPhotoImage(ファイル名)でファイルを読み込み表示させた。ディスクへの保存のプロセスが入るので、パフォーマンス的にも良くなさそうだし、余計なファイルは作らないようにしたい。そのため、matplotlibのグラフをtkinterへデータとして受け渡したい。
matplotlibからImageオブジェクトを作成して、PhotoImageで読み込むといったことができないか、いろいろ調べて試してみたけど、PhotoImageはImageを読み込むようになっていないようで、うまくいかない。最終的に、io.BytesIOでグラフの画像データをバイト列のデータに変換し、それをPhotoImageで読みこませることで対応できた。PhotoImageは、ファイル名で画像ファイルを読み込むほか、データでの読み込みもできるよう。
次に2。
ラジオボタンで、a, b, cをテキストボックスから入れるパターンとランダムに決めるパターンを切りかえれるようにする。
ラジオボタンのコードは下の通り。varでラジオボタンのチェックが入っている場所を決め、ボタンを押したときのメソッド(button1_method)の中でどちらにチェックが入っているかで場合分けする。
self.var = ttk.IntVar()
self.widgtRadiobut01 = ttk.Radiobutton(self.frame, value=0, variable=self.var, text='Input')
self.widgtRadiobut02 = ttk.Radiobutton(self.frame, value=1, variable=self.var, text='Random(-10~10)')
self.var.set(value=0)
def button1_method(self):
var = self.var.get()
if var == 0:
処理1
elif var == 1:
処理2
実行すると、下のような表示となる。
最後にtkinterの機能after。
これを使うと、afterの中の(ミリ秒、メソッド)で指定した通り、特定の時間を待ってからメソッドを実行する。
func1.after(2000, self.button1_method)
button1_methodの中でafterを使ったので、再帰的に呼び出され自動的に更新され続ける。tkinterのチュートリアルでは、タイマーのサンプルが紹介されていたけど自然な使い方だった。
今回修正したコードは下の通り。
次回ももう少しtkinterをさわるかも。
import tkinter as ttk
import matplotlib.pyplot as plt
from PIL import Image
import io
import random
START_VAR = -20
END_VAR = 20
class Function(ttk.Tk):
def __init__(self):
super().__init__()
self.title('Function')
self.geometry("400x400")
self.resizable(0, 0)
self.frame = ttk.Frame(self, borderwidth=10)
self.frame.grid(column=8, row=8)
self.widgt1 = ttk.Label(self.frame, text="y = a * x^2 + b * x + c")
self.widgt2 = ttk.Entry(self.frame, text="a", width=10)
self.widgt3 = ttk.Entry(self.frame, text="b", width=10)
self.widgt4 = ttk.Entry(self.frame, text="c", width=10)
self.widgt5 = ttk.Button(self.frame, text="Show", bg="white")
self.widgt5['command'] = self.button1_method
self.widgt6 = ttk.Label(self.frame)
self.var = ttk.IntVar()
self.widgtRadiobut01 = ttk.Radiobutton(self.frame, value=0, variable=self.var, text='Input')
self.widgtRadiobut02 = ttk.Radiobutton(self.frame, value=1, variable=self.var, text='Random(-10~10)')
self.var.set(value=0)
self.widgt1.grid(column=0, row=1, columnspan=8)
self.widgt2.grid(column=0, row=2)
self.widgt3.grid(column=1, row=2)
self.widgt4.grid(column=2, row=2)
self.widgt5.grid(column=3, row=2)
self.widgt6.grid(column=0, row=3, columnspan=4)
self.widgtRadiobut01.grid(column=0, row=0)
self.widgtRadiobut02.grid(column=2, row=0)
def button1_method(self):
var = self.var.get()
if var == 0:
imgdata = get_graph_data(self.widgt2.get(), self.widgt3.get(), self.widgt3.get())
img = ttk.PhotoImage(data=imgdata)
self.widgt6.configure(image=img)
self.widgt6.image = img
elif var == 1:
num1 = random.randint(-10, 10)
num2 = random.randint(-10, 10)
num3 = random.randint(-10, 10)
imgdata = get_graph_data(num1, num2, num3)
img = ttk.PhotoImage(data=imgdata)
self.widgt6.configure(image=img)
self.widgt6.image = img
func1.after(2000, self.button1_method)
##############################
##############################
def get_graph_data(var_a, var_b, var_c):
x = []
y = []
plt.figure(figsize=(3.2, 2))
for i in range(START_VAR, END_VAR):
x.append(i)
y.append(int(var_a) * (i ** 2) + int(var_b) * i + int(var_c))
print(x)
print(y)
plt.plot(x, y)
plt.tight_layout()
buf = io.BytesIO()
plt.savefig(buf, format='png')
buffdata = buf.getvalue()
return buffdata
##############################
if __name__ == "__main__":
func1 = Function()
func1.mainloop()