接着上一篇给代码添加了表格功能,方便更好的处理数据。
import json
import os
from datetime import datetime
from tkinter import *
from tkinter import messagebox
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import pandas as pd
def update_data(filename, data_name, value):
"""更新数据文件中的数据"""
with open(filename, 'r') as file:
data = json.load(file)
if data_name not in data:
data[data_name] = []
current_time = datetime.now().isoformat()
if data[data_name]:
prev_value = data[data_name][-1]['value']
difference = value - prev_value
else:
difference = None
data[data_name].append({"time": current_time, "value": value, "difference": difference})
with open(filename, 'w') as file:
json.dump(data, file)
def read_data(filename):
"""从数据文件中读取数据"""
if os.path.exists(filename):
with open(filename, 'r') as file:
return json.load(file)
return {}
class DataApp:
def __init__(self, master):
self.master = master
self.master.title("数据记录器")
self.filename = 'data_records.json'
self.init_data_file() # 调用初始化数据文件的方法
# 创建输入框和按钮
Label(master, text="数据名称:").grid(row=0)
self.data_name_entry = Entry(master)
self.data_name_entry.grid(row=0, column=1)
Label(master, text="数据值:").grid(row=1)
self.data_value_entry = Entry(master)
self.data_value_entry.grid(row=1, column=1)
self.update_button = Button(master, text="更新数据", command=self.update_data_gui)
self.update_button.grid(row=2, column=1)
self.analyze_button = Button(master, text="分析数据", command=self.analyze_data)
self.analyze_button.grid(row=3, column=1)
self.clear_button = Button(master, text="清空数据库", command=self.clear_data)
self.clear_button.grid(row=4, column=1)
self.quit_button = Button(master, text="退出", command=master.quit)
self.quit_button.grid(row=5, column=1)
# 图表区域
self.figure = Figure(figsize=(6, 4), dpi=100)
self.ax = self.figure.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.figure, master=master)
self.canvas.get_tk_widget().grid(row=0, column=2, rowspan=6)
# 初始化数据文件(如果文件不存在,则创建空字典)
def init_data_file(self):
if not os.path.exists(self.filename):
with open(self.filename, 'w') as file:
json.dump({}, file)
# 数据清空功能
def clear_data(self):
confirm = messagebox.askyesno("警告", "您确定要清空所有数据吗?此操作不可逆!")
if confirm:
with open(self.filename, 'w') as file:
json.dump({}, file)
messagebox.showinfo("成功", "数据已清空。")
self.analyze_data() # 可选:清空后重新分析数据
else:
messagebox.showinfo("取消", "数据清空操作已取消。")
# GUI版本的更新数据函数
def update_data_gui(self):
data_name = self.data_name_entry.get()
try:
new_value = float(self.data_value_entry.get())
update_data(self.filename, data_name, new_value)
messagebox.showinfo("成功", f"数据 {data_name} 已更新,并记录了差值和时间。")
except ValueError:
messagebox.showerror("错误", "请输入有效的数字!")
# 数据分析图表函数
def analyze_data(self):
data_name = self.data_name_entry.get()
data = read_data(self.filename)
if data_name in data:
times = [record["time"] for record in data[data_name]]
values = [record["value"] for record in data[data_name]]
differences = [record["difference"] for record in data[data_name]]
self.ax.clear()
self.ax.plot(times, values, label='Values', marker='o')
self.ax.plot(times, differences, label='Differences', marker='x')
# 在每个点旁边添加数值标签
for i, (val, diff) in enumerate(zip(values, differences)):
self.ax.text(times[i], val, f'{val:.2f}', ha='center', va='bottom')
self.ax.text(times[i], diff, f'{diff:.2f}', ha='center', va='top')
self.ax.legend()
self.ax.set_title(f"{data_name} Analysis")
self.canvas.draw()
# 添加Excel导出按钮
self.export_button = Button(self.master, text="导出至Excel", command=lambda: self.export_to_excel(data_name))
self.export_button.grid(row=6, column=1)
else:
messagebox.showerror("错误", f"数据名称 {data_name} 未找到!")
# Excel导出功能
def export_to_excel(self, data_name):
data = read_data(self.filename)
if data_name in data:
records = data[data_name]
df = pd.DataFrame(records)
df['Time'] = pd.to_datetime(df['time'], format='ISO8601') # 明确指定格式
df.rename(columns={'time': 'Time'}, inplace=True)
# 使用ExcelWriter,并设置if_sheet_exists为'replace'来覆盖已存在的工作表
with pd.ExcelWriter('data_records.xlsx', engine='openpyxl', mode='a', if_sheet_exists='replace') as writer:
df.to_excel(writer, sheet_name=data_name, index=False)
messagebox.showinfo("成功", f"数据 {data_name} 已导出到Excel文件。")
else:
messagebox.showerror("错误", f"数据名称 {data_name} 未找到!无法导出。")
# 主程序入口
if __name__ == "__main__":
root = Tk()
app = DataApp(root)
root.mainloop()
效果如下