Tkinterにボタンやテキストボックスを配置しCSVファイルなどのデータを選択し選択したデータの
グラフをMatplotlibで表示させたり、色を変えたりできるコードを作っています。
基本的には作れていますが、1つ1つのボタンなどを記述して書いているとコードが長くなりすぎて
見づらくなってしまうので、for文を使ってTkinterのウイジェットを配置しようとコードを改造しています。
ウイジェットの配置はできるのですが、それぞれのボタンなどのコマンドを紐づけするのに苦労しています。
ベースとなるやりたいことができているコード
1、データ選択
(ボタンでデータを選択しテキストボックスにファイル名を表示、プロットに代入グラフ表示)
2、表示データの色の変更
(プロットカラーの初期設定はボタンの色、ボタンクリックでカラー選択、ボタンとプロットの色変更)
3、データの表示、非表示
(初期設定でプロット表示、チェックボックスをはずすとプロット非表示)
import os import csv import numpy as np import pandas as pd import tkinter import tkinter as tk from tkinter import font import tkinter.ttk as ttk import matplotlib.pyplot as plt import tkinter.filedialog as fl import tkinter.colorchooser from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # CSV Data Graph Base fig = plt.Figure(dpi=100, figsize=(8,6)) ax = fig.add_subplot() ax.set_title("Test Graph", pad=25) ax.set_xlabel("X Axis", labelpad=10) ax.set_ylabel("Y Axis", labelpad=20) ax.grid(True) ax.set_xlim(0, 5) ax.set_xticks(np.arange(0, 6, 0.5)) ax.set_ylim(-0.5, 0.5) ax.set_yticks(np.arange(-0.5, 0.6, 0.1)) h1, = ax.plot([], [], color="blue", linewidth=1, linestyle="-") h2, = ax.plot([], [], color="red", linewidth=1, linestyle="-") class Application(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) self.frame1 = ttk.Frame(self, relief="ridge", width=800, height=600) self.frame1.pack(anchor="w", side="left", fill="x") # Canvas Matplotlib PullDown Front self.canvas1 = FigureCanvasTkAgg(fig, self.frame1) self.canvas1.draw() self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.frame2 = ttk.Frame(self, relief="ridge", width=800, height=600) self.frame2.pack(anchor="n", side="left", fill="x") label = ttk.Label(self.frame2,text="CSV Data Select") label.grid(row=0, column=0, columnspan=5, padx=20, pady=10) # CSV Data 1 の選択 self.data1_bln = tk.BooleanVar() self.data1_bln.set(True) self.chk_data_1 = ttk.Checkbutton(self.frame2,variable=self.data1_bln,text="Data1 表示",command=self.data1_hidden) self.chk_data_1.grid(row=1, column=0, padx=10, pady=10) self.data1 = tkinter.StringVar() self.data1_Entry = tk.Entry(self.frame2,textvariable=self.data1,justify="center",width=10) self.data1_Entry.grid(row=1, column=1, sticky=tk.W, padx=10, pady=10) self.data1_Button = tk.Button(self.frame2,text="データ1 選択",width=12,command=self.select_data1) self.data1_Button.grid(row=1, column=3, padx=10, pady=10) self.color1_Button = tk.Button(self.frame2,text="データ1 色",width=10,background="blue",command=self.select_color1) self.color1_Button.grid(row=1, column=4, padx=10, pady=10) """ Data 1 データ選択 """ def select_data1(self): data_1 = os.path.abspath(os.path.dirname(__file__)) data_1_DirPath = fl.askopenfilename(filetypes=[("", "*.csv")], initialdir=data_1) data_1_file = os.path.splitext(os.path.basename(data_1_DirPath))[0] self.data1.set(data_1_file) df0 = pd.read_csv(data_1_DirPath, index_col=None) self.x1 = df0["X"] self.y1 = df0["Y"] h1.set_xdata(self.x1) h1.set_ydata(self.y1) self.canvas1.draw() """ Data 1 カラー """ def select_color1(self): button_color1 = tkinter.colorchooser.askcolor() self.color1_Button.configure(background=button_color1[1]) h1.set_color(button_color1[1]) self.canvas1.draw() """ Data 1 データ非表示 """ def data1_hidden(self): if self.data1_bln.get(): h1.set_xdata(self.x1) h1.set_ydata(self.y1) self.canvas1.draw() else: h1.set_xdata([]) h1.set_ydata([]) self.canvas1.draw() if __name__ == "__main__": app = Application() app.geometry("1200x600+10+10") app.title("テスト") app.mainloop()
読み込むサンプルデータファイル
data1.csv data2.csv
X Y X Y
0 0 0 0
0.1 -0.098 0.1 0
0.2 -0.2206504 0.2 0.103
0.3 -0.298896862 0.3 0.2306504
0.4 -0.304096311 0.4 0.308896862
0.5 -0.249144635 0.5 0.314096311
0.6 -0.174277652 0.6 0.259144635
0.7 -0.121153529 0.7 0.184277652
0.8 -0.111721969 0.8 0.131153529
0.9 -0.141430161 0.9 0.121721969
1 -0.187121213 1 0.151430161
1.1 -0.222559123 1.1 0.197121213
1.2 -0.232199955 1.2 0.232559123
1.3 -0.216695681 1.3 0.242199955
1.4 -0.189132519 1.4 0.226695681
1.5 -0.165850128 1.5 0.199132519
1.6 -0.157581613 1.6 0.175850128
1.7 -0.165276309 1.7 0.167581613
1.8 -0.181700559 1.8 0.175276309
1.9 -0.19679042 1.9 0.191700559
2 -0.203284028 2 0.20679042
問題のコード、変更点と問題点
1、クリックしたボタンの背景色を変更、これは問題なし
2、ボタンでファイルダイアログを開くまではできるが、対になるテキストボックスにファイル名を
入れることができない。どうやってテキストボックスを選択するのか??
3、同じようにイベントの発生したウイジェットと、チェックボックス、グラフ・プロットとの関連付けをどうするのか
# CSV Data Graph Base fig = plt.Figure(dpi=100, figsize=(8,6)) ax = fig.add_subplot() ax.set_title("Test Graph", pad=25) ax.set_xlabel("X Axis", labelpad=10) ax.set_ylabel("Y Axis", labelpad=20) ax.grid(True) ax.set_xlim(0, 5) ax.set_xticks(np.arange(0, 6, 0.5)) ax.set_ylim(-0.5, 0.5) ax.set_yticks(np.arange(-0.5, 0.6, 0.1)) h1, = ax.plot([], [], color="blue", linewidth=1, linestyle="-") h2, = ax.plot([], [], color="red", linewidth=1, linestyle="-") # データファイル index_no = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] datatext = ["Data 1", "Data 2", "Data 3", "Data 4", "Data 5", "Data 6", "Data 7", "Data 8"] datacolor = ["blue", "red", "green", "magenta", "cyan", "yellow", "purple", "lightgreen"] class Application(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) self.frame1 = ttk.Frame(self, relief="ridge", width=1200, height=600) self.frame1.pack(anchor="w", side="left", fill="x") # Canvas Matplotlib self.canvas1 = FigureCanvasTkAgg(fig, self.frame1) self.canvas1.draw() self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.frame2 = ttk.Frame(self, relief="ridge", width=1200, height=600) self.frame2.pack(anchor="n", side="left", fill="x") label = ttk.Label(self.frame2, text="This is the Page 1") label.grid(row=0, column=0, columnspan=5, padx=40, pady=10) # データ表示ウイジェットの作成 self.string_vars = [] # enumerateを使わないで:zip_longestを使うのは、 # 条件などにより様々なリスト要素の組み合わせを作れるようにするため for j, name, code in zip_longest(index_no, datatext, datacolor): if j >= 5: break i = len(self.string_vars) self.string_vars.append(tkinter.StringVar()) pfbln = tk.BooleanVar() pfbln.set(True) chk_pfbln = ttk.Checkbutton(self.frame2, variable=pfbln, text=name + "表示") chk_pfbln.grid(row=j + 1, column=0, padx=10, pady=10) pfe = tk.Entry(self.frame2, textvariable=self.string_vars[i], justify="center", width=10) pfe.grid(row=j + 1, column=1, padx=10, pady=10) pfb = tk.Button(self.frame2, text=name + " 選択") pfb.bind("<Button-1>", self.select_data) pfb.grid(row=j + 1, column=2, padx=10, pady=10) pfbc = tk.Button(self.frame2, text="カラー選択", bg=code) pfbc.bind("<Button-1>", self.select_color) pfbc.grid(row=j + 1, column=3, padx=10, pady=10) def select_color(self, event): color1 = tkinter.colorchooser.askcolor() event.widget["bg"] = color1[1] return "break" def select_data(self, event): data = os.path.abspath(os.path.dirname(__file__)) self.data_DirPath = fl.askopenfilename(filetypes=[("", "*.csv")], initialdir=data) data_name = os.path.splitext(os.path.basename(self.data_DirPath))[0] return "break" if __name__ == "__main__": app = Application() app.geometry("1200x600+10+10") app.title("テスト") app.mainloop()
ボタンの数が多くなる予定なのでできれば、for文を使って効率よくコードを書きたいと思っています。
一番の問題、わからないことは、イベントの発生したウイジェットとその他のウイジェットを関連付けることです。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/09 02:27
2020/07/09 03:21 編集
2020/07/10 03:55
2020/07/10 04:48