ちょいめも

物理/Python/Cの雑記帳

Python + Tkinterでグラフ表示

import os
import re
import numpy as np
import pandas as pd
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.filedialog as tkdialog
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

#----- 定義 & グローバル変数 -----
NUM_FILE = 3
NUM_GRAPH = 5

label = [0 for i in range(NUM_FILE)]
chk_var = [0 for i in range(NUM_FILE)]
chk_box = [0 for i in range(NUM_FILE)]
edit_box = [0 for i in range(NUM_FILE)]
graph = [[0 for i in range(NUM_FILE)] for j in range(NUM_GRAPH)]
data = [0 for i in range(NUM_FILE)]
ax = [0 for i in range(NUM_GRAPH)]

#グラフ
plt.style.use('ggplot')
fig = plt.Figure(figsize=(12, 6))#, dpi=100) #(col,row)
#↓この書き方はグラフだけ個別に開いてしまう、なぜかは不明
#fig, axes = plt.subplots(nrows = 2, ncols = 2, figsize=(5, 5), sharex = False)

x_name='x'
y_name=['a','b','c','d','e'] #グラフの数に対応 csvの列名
def_data_name = 'no data' #凡例 デフォルト

#グラフ描画
def draw():

	#軸範囲
	y_min = 0
	y_max = 150
	x_min = [0 for i in range(NUM_GRAPH)]
	x_max = [0 for i in range(NUM_GRAPH)]

	for i in range(NUM_FILE):
		#チェックボックスにチェックが入っている時
		if chk_var[i].get():
			data[i] = pd.read_csv(edit_box[i].get())

			for j in range(NUM_GRAPH):
				x = data[i][x_name].values
				y = data[i][y_name[j]].values
				graph[j][i].set_data(x, y)

				#軸設定 軸範囲手動
				if auto_scale_chk_box_var.get():
					if len(x_axis_min_edit_box.get()) > 0 and len(x_axis_max_edit_box.get()) > 0 and float(x_axis_max_edit_box.get()) - float(x_axis_min_edit_box.get()) > 0:
						ax[j].set_xlim(float(x_axis_min_edit_box.get()), float(x_axis_max_edit_box.get()))
				#軸範囲 自動設定
				else:
					x_max[j] = x.max() if x.max() > x_max[j] else x_max[j]
					x_min[j] = x.min() if x.min() > x_min[j] else x_min[j]
					ax[j].set_xlim(x_min[j], x_max[j])
				ax[j].set_ylim(y_min, y_max)

				graph[j][i].set_label('File%d %s' % (i+1, y_name[j]))
				ax[j].legend()

		else:
			for j in range(NUM_GRAPH):
				graph[j][i].set_data([], [])
				graph[j][i].set_label(def_data_name)
				ax[j].legend()


def combo1list():
	if rdo_var.get() == 0:
		combo1['values'] = ('2', '4', '6', '8', '10')
	elif rdo_var.get() == 1:
		combo1['values'] = ('5', '10', '15', '20', '25')
	combo1.current(0) #デフォルト値の最初の要素


def combo1_selected(event):
	print('combo1 = %s' % val1.get())


def combo2_selected(event):
	print('combo2 = %s' % val2.get())


def file_dialog(event):
	fname = tkdialog.askopenfilename(filetypes=[('data files','*.csv')], initialdir=os.getcwd())
	#ボタンの名前から番号を取り出す(文字列から数値を取り出す)
	index = int(re.sub(r'\D', '', event.widget["text"]))-1
	#入力ボックスの文字を消す
	edit_box[index].delete(0, tk.END)
	edit_box[index].insert(tk.END, fname)

#グラフ更新
def update():
	draw()
	canvas.draw()


#グラフx軸変更
def change_axis_range():
	if auto_scale_chk_box_var.get():
		for i in range(NUM_GRAPH):
			if len(x_axis_min_edit_box.get()) > 0 and len(x_axis_max_edit_box.get()) > 0 and float(x_axis_max_edit_box.get()) - float(x_axis_min_edit_box.get()) > 0:
				ax[j].set_xlim(float(x_axis_min_edit_box.get()), float(x_axis_max_edit_box.get()))
	draw()
	canvas.draw()


if __name__ == '__main__':

    #----- tk -----
	root = tk.Tk()
	root.title('Title')
	root.geometry('1300x600')

	#グラフファイル入力、設定フレーム
	setting_frame = tk.Frame(root, padx=10, pady=5)
	#グラフ表示フレーム
	graph_frame   = tk.Frame(root, padx=10, pady=5)

	#tkinterに追加するcanvasにfigを追加する
	canvas = FigureCanvasTkAgg(fig, master=graph_frame)
	canvas.get_tk_widget().pack(side=tk.LEFT)


	#グラフファイル入力 ラベル
	chk_box_label = tk.Label(setting_frame, text='Graph ON/OFF')
	chk_box_label.grid(row=0, column=1, padx=1, pady=1, sticky=tk.W)

	edit_box_label = tk.Label(setting_frame, text='File Path')
	edit_box_label.grid(row=0, column=2, padx=1, pady=1, sticky=tk.W)


	#ファイル入力
	for i in range(NUM_FILE):
		#ラベル
		label[i] = tk.Label(setting_frame, text='File %d' % (i+1))
		label[i].grid(row=i+1, column=0, padx=10, pady=1)
		#チェックボックス
		chk_var[i] = tk.IntVar()
		chk_box[i] = tk.Checkbutton(setting_frame, variable=chk_var[i], command=update)
		chk_box[i].grid(row=i+1, column=1, padx=1, pady=1)
		#入力ボックス
		edit_box[i] = tk.Entry(setting_frame, width=100)
#		edit_box[i].insert(tk.END,'ファイルパスを入力してください')
		edit_box[i].insert(tk.END,'D:\\python\\Anaconda3\\PythonScript\\graph_gui\\curveplot_sample%s.csv' % (i+1))
		edit_box[i].grid(row=i+1, column=2, padx=10, pady=1)

		#ファイルダイアログ
		fopen_button = tk.Button(setting_frame, text='File%d open' % (i+1), width=10)
		fopen_button.bind("<ButtonRelease-1>", file_dialog) #左ボタンを押してそのボタンを放した時に発生
		fopen_button.grid(row=i+1, column=3, padx=1, pady=1)


	#グラフ設定
	auto_scale_chk_box_label = tk.Label(setting_frame, text='auto scale ON/OFF')
	auto_scale_chk_box_label.grid(row=0, column=4, padx=10, pady=1, sticky=tk.W)

	auto_scale_chk_box_var = tk.IntVar()
	auto_scale_chk_box = tk.Checkbutton(setting_frame, variable=auto_scale_chk_box_var, command=change_axis_range)
	auto_scale_chk_box.grid(row=1, column=4, padx=1, pady=1)

	x_axis_min_label = tk.Label(setting_frame, text='x axis min')
	x_axis_min_label.grid(row=0, column=5, padx=10, pady=1, sticky=tk.W)
	x_axis_min_edit_box = tk.Entry(setting_frame, width=10)
	x_axis_min_edit_box.grid(row=1, column=5, padx=10, pady=1)

	x_axis_max_label = tk.Label(setting_frame, text='x axis max')
	x_axis_max_label.grid(row=0, column=6, padx=10, pady=1, sticky=tk.W)
	x_axis_max_edit_box = tk.Entry(setting_frame, width=10)
	x_axis_max_edit_box.grid(row=1, column=6, padx=10, pady=1)

	#Combobox1 ドロップダウンリストとラジオボタン テスト配置
	rdo_var = tk.IntVar()
	rdo_var.set(0)
	rdo0 = tk.Radiobutton(setting_frame, text='1', variable=rdo_var, value=0, command=combo1list)
	rdo0.grid(row=2, column=4, padx=1, pady=1)
	rdo1 = tk.Radiobutton(setting_frame, text='2', variable=rdo_var, value=1, command=combo1list)
	rdo1.grid(row=2, column=5, padx=1, pady=1)

	val1 = tk.StringVar()
	combo1 = ttk.Combobox(setting_frame, state='readonly', textvariable=val1)
	combo1.bind('<<ComboboxSelected>>', combo1_selected)
	combo1list()
	combo1.grid(row=3, column=4, padx=1, pady=1)

	#Combobox2 テスト配置
	val2 = tk.StringVar()
	combo2 = ttk.Combobox(setting_frame, state='readonly', textvariable=val2)
	combo2.bind('<<ComboboxSelected>>', combo2_selected)
	combo2['values'] = ('TEST1', 'TEST2', 'TEST3')
	combo2.current(0) #デフォルト値の最初の要素
	combo2.grid(row=4, column=4, padx=1, pady=1)


	#グラフ (行、列、場所)
	graph_pos = [1,2,3,5,6] #グラフの位置
	for i in range(NUM_GRAPH):
		ax[i] = fig.add_subplot(2, 3, graph_pos[i])
		for j in range(NUM_FILE):
			graph[i][j], = ax[i].plot([], [], label=def_data_name)
		ax[i].legend()

	fig.tight_layout()


	setting_frame.pack(anchor=tk.NW) #tk.NW:左上寄せ
	graph_frame.pack(anchor=tk.NW) #tk.NW:左上寄せ

	root.mainloop() #ここまで

batファイルからpythonスクリプトを起動
・RunScript.bat
cd /d %~dp0
D:\python\Anaconda3\python.exe test.py
・RunScript.vbs
Dim oShell
Set oShell = WScript.CreateObject ("WSCript.shell")
oShell.run "D:\python\Anaconda3\PythonScript\graph_gui\RunScript.bat",0
Set oShell = Nothing