ちょいめも

物理/Python/Cの雑記帳

python+tkinterでグラフ表示 classで書き直し

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

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


class Application(tk.Frame):

	def __init__(self, master=None):

		self.label = [0 for i in range(NUM_FILE)]
		self.chk_var = [0 for i in range(NUM_FILE)]
		self.chk_box = [0 for i in range(NUM_FILE)]
		self.edit_box = [0 for i in range(NUM_FILE)]
		self.fopen_button = [0 for i in range(NUM_FILE)]

		self.graph = [[0 for i in range(NUM_FILE)] for j in range(NUM_GRAPH)]
		self.data = [0 for i in range(NUM_FILE)]
		self.ax = [0 for i in range(NUM_GRAPH)]

		self.filename = [0 for i in range(NUM_FILE)]
		self.xname = [0 for i in range(NUM_GRAPH)]
		self.max_index = [[0 for i in range(NUM_GRAPH)] for j in range(NUM_FILE)]
		self.max_value = [[0 for i in range(NUM_GRAPH)] for j in range(NUM_FILE)]


		super().__init__(master)
		self.pack()
		self.input_file_label(0, 1)
		self.input_file_entry(1, 0)
		self.setting_x_axis(0, 4)
		self.save_figure_button(1, 7)
		self.save_value_button(2, 7)
		self.sub_win_button(0, 8)

		#グラフ
		plt.style.use('ggplot')
		fig = plt.Figure(figsize=(12, 5))#, dpi=100) #(col,row)
		#tkinterに追加するcanvasにfigを追加する
		self.canvas = FigureCanvasTkAgg(fig, master)
		self.canvas.get_tk_widget().pack()

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

		fig.tight_layout()

		self.frame_out = tk.Frame()
		self.test_edit_box()
		self.frame_out.pack(side=tk.LEFT, padx=0)


	#グラフ描画
	def draw(self):
		#軸範囲
		y_min = 0
		y_max = 150
		x_min = 0
		x_max = 0

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


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

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

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

					#値出力用に格納 [file][graph] 最初にファイルをもってくることでファイルの次元を指定してグラフの値を全て書きだせるようにする
					self.xname[j] = y_name[j]
					self.max_index[i][j] = y.argmax()
					self.max_value[i][j] = y.max()

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


	def save_value_button(self, r, c):
		self.savevalue_button = tk.Button(self, text='Save Value', width=10)
		self.savevalue_button.bind("<ButtonRelease-1>", self.save_value) #左ボタンを押してそのボタンを放した時に発生
		self.savevalue_button.grid(row=r, column=c, padx=1, pady=1)


	def save_value(self, event):
		self.draw()

		#default file name取得
		val_name = ''
		for i in range(NUM_FILE):
			if self.chk_var[i].get():
				val_name = val_name + '_' + self.filename[i]

		value_data = self.xname
		col_name1 = 'filename'
		col_name2 = 'pos'
		for i in range(NUM_FILE):
			if self.chk_var[i].get():
				col_name1 = np.vstack([col_name1, self.filename[i], self.filename[i]])
				col_name2 = np.vstack([col_name2, 'peak_index', 'peak_value'])
				value_data = np.vstack([value_data, self.max_index[i], self.max_value[i]])

		#列名挿入
		value_data = np.hstack([col_name1, col_name2, value_data])

		save_value_name = tkdialog.asksaveasfilename(filetypes=[('data files','*.csv')], initialdir=os.getcwd(), initialfile=val_name)
		np.savetxt(save_value_name + '.csv', value_data.T, fmt='%s', delimiter = ',')


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

		self.edit_box_label = tk.Label(self, text='File Path')
		self.edit_box_label.grid(row=r, column=c+1, padx=10, pady=1, sticky=tk.W)


	def input_file_entry(self, r, c):
		for i in range(NUM_FILE):
			self.label[i] = tk.Label(self, text='File%d' % (i+1))
			self.label[i].grid(row=i+r, column=c, padx=10, pady=1)
			#チェックボックス
			self.chk_var[i] = tk.IntVar()
			self.chk_box[i] = tk.Checkbutton(self, variable=self.chk_var[i], command=self.update)
			self.chk_box[i].grid(row=i+r, column=c+1, padx=1, pady=1)
			#入力ボックス
			self.edit_box[i] = tk.Entry(self, width=60)
			self.edit_box[i].insert(tk.END,'input file path (full path)')
			self.edit_box[i].grid(row=i+r, column=c+2, padx=10, pady=1)

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


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


	def save_figure_button(self, r, c):
		self.save_button = tk.Button(self, text='Save Figure', width=10)
		self.save_button.bind("<ButtonRelease-1>", self.save_figure) #左ボタンを押してそのボタンを放した時に発生
		self.save_button.grid(row=r, column=c, padx=1, pady=1)


	def save_figure(self, event):
		#default file name取得
		fig_name = ''
		for i in range(NUM_FILE):
			if self.chk_var[i].get():
				fig_name = fig_name + '_' + self.filename[i]

		save_figure_name = tkdialog.asksaveasfilename(filetypes=[('data files','*.png')], initialdir=os.getcwd(), initialfile=fig_name)
		self.draw()
		self.canvas.draw()
		self.canvas.print_figure(save_figure_name, dpi=300)


	def setting_x_axis(self, r, c):

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

		self.auto_scale_chk_box_var = tk.IntVar()
		auto_scale_chk_box = tk.Checkbutton(self, variable=self.auto_scale_chk_box_var, command=self.change_axis_range)
		auto_scale_chk_box.grid(row=r+1, column=c, padx=1, pady=1)

		x_axis_min_label = tk.Label(self, text='x axis min')
		x_axis_min_label.grid(row=r, column=c+1, padx=1, pady=1, sticky=tk.W)
		self.x_axis_min_edit_box = tk.Entry(self, width=10)
		self.x_axis_min_edit_box.grid(row=r+1, column=c+1, padx=1, pady=1)

		x_axis_max_label = tk.Label(self, text='x axis max')
		x_axis_max_label.grid(row=r, column=c+2, padx=1, pady=1, sticky=tk.W)
		self.x_axis_max_edit_box = tk.Entry(self, width=10)
		self.x_axis_max_edit_box.grid(row=r+1, column=c+2, padx=1, pady=1)


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

		self.canvas.draw()


	#設定ウインドウ呼び出しボタン 別ウインドウが開く
	def sub_win_button(self, r, c):
		sub_win_button = tk.Button(self, text='Sub Window', width=10)
		sub_win_button.bind("<ButtonRelease-1>", self.sub_win_event) #左ボタンを押してそのボタンを放した時に発生
		sub_win_button.grid(row=r, column=c, padx=1, pady=1)


	def sub_win_event(self, event):
		sub_win = tk.Toplevel()
		sub_win.title("Setting")
		sub_win.geometry('300x200')

		self.sub_win_edit_box = tk.Entry(sub_win, width=10)
		try:
			self.sub_win_edit_box.insert(tk.END, self.save_sub_win_value)
		except:
			self.sub_win_edit_box.insert(tk.END, 0)
		self.sub_win_edit_box.grid(row=0, column=0, padx=1, pady=1)

		save_button = tk.Button(sub_win, text="Save Value", width=10)
		save_button.bind("<ButtonRelease-1>", self.sub_win_out) #左ボタンを押してそのボタンを放した時に発生
		save_button.grid(row=1, column=0, padx=1, pady=1)

		close_button = tk.Button(sub_win, text="CLOSE", width=10, command=sub_win.destroy)
		close_button.grid(row=2, column=0, padx=1, pady=1)


	#サブウインドウの値を保存
	def sub_win_out(self, event):
		self.save_sub_win_value = self.sub_win_edit_box.get()


	def update(self):
		self.draw()
		self.canvas.draw()

		#self.test_edit_box()でテキストボックスが生成されるので、destroyで削除する
		self.edit_box_out.destroy()
		self.test_edit_box()

		try:
			print(self.save_sub_win_value)
		except:
			print('no data')

	def test_edit_box(self):

		name=['a', 'b', 'c', 'd', 'e', 'f']

		for i in range(NUM_FILE):
			label1 = tk.Label(self.frame_out, text='File{}'.format(i+1))
			label1.grid(row=0, column=i+1, padx=2, pady=0)

		for i in range(len(name)):
			label2 = tk.Label(self.frame_out, text='{}'.format(name[i]))
			label2.grid(row=i+1, column=0, padx=2, pady=0)

		for j in range(len(name)):
			for i in range(NUM_FILE):
				self.edit_box_out = tk.Entry(self.frame_out, width=8)
				if self.chk_var[i].get():
					self.edit_box_out.insert(tk.END, '{:.3f}'.format(self.max_value[i][0])) #一個目のグラフ #[file][graph]
				else:
					self.edit_box_out.insert(tk.END, 0) #一個目のグラフ #[file][graph]
				self.edit_box_out.configure(state='readonly')
				self.edit_box_out.grid(row=j+1, column=i+1, padx=2, pady=0)


if __name__ == '__main__':
	root = tk.Tk()
#	root.resizable(0,0) #ウィンドウのサイズ固定
	root.title('Title1')
	root.geometry('1300x720')
	root.iconbitmap('icon.ico')
	app = Application(master=root)
	app.mainloop()
ret = [data[i*4+4:i*4+4+4].mean() for i in range(5)]
#1-3
ret2 = [data[i*4+4]-data[i*4+6] for i in range(5)]
#4-2
ret3 = [data[i*4+7]-data[i*4+5] for i in range(5)]
import os
import numpy as np
import tkinter as tk
import tkinter.messagebox as tkmsg

VER = 1.00
app_dir = 'D:\\python\\Anaconda3\\PythonScript\\app'

latest_version = np.array(os.listdir(app_dir)).astype(float).max()
root = tk.Tk()
if latest_version > VER:
	ret = tkmsg.askokcancel('INFO', 'The latest ver is available\nVer.{:.2f} → Ver.{:.2f}\nOK:Open the folder'.format(VER, latest_version))
	if ret == True:
		os.popen('explorer {}'.format(app_dir))
root.mainloop()