代码:
python">import tkinter as tk
from tkinter import ttk
import math
from tkinter.font import Fontclass StorageCalculator:def __init__(self, root):self.root = rootself.root.title("监控视频存储计算器")self.root.geometry("600x800")self.root.configure(bg='#f0f0f0')# 设置主题和样式self.style = ttk.Style()self.style.theme_use('clam') # 使用clam主题作为基础# 定义颜色方案self.colors = {'primary': '#2196F3', # 主色调'secondary': '#64B5F6', # 次要色调'bg': '#f0f0f0', # 背景色'text': '#212121', # 文字颜色'success': '#4CAF50' # 成功色}# 设置自定义字体self.title_font = Font(family="微软雅黑", size=12, weight="bold")self.normal_font = Font(family="微软雅黑", size=10)self.result_font = Font(family="微软雅黑", size=11, weight="bold")# 配置样式self.style.configure('Title.TLabel', font=self.title_font, background=self.colors['bg'],foreground=self.colors['primary'])self.style.configure('Normal.TLabel', font=self.normal_font,background=self.colors['bg'])self.style.configure('Custom.TButton',font=self.normal_font,background=self.colors['primary'],padding=(20, 10))self.style.configure('Tab.TNotebook',background=self.colors['bg'])self.style.configure('Result.TLabelframe',background=self.colors['bg'])# 创建主标题self.create_header()# 创建notebookself.notebook = ttk.Notebook(root, style='Tab.TNotebook')self.notebook.pack(fill='both', expand=True, padx=20, pady=(0, 20))# 创建计算页面self.create_forward_page()self.create_reverse_page()# 创建页脚self.create_footer()def create_header(self):"""创建头部标题区域"""header_frame = ttk.Frame(self.root)header_frame.pack(fill='x', padx=20, pady=20)title = ttk.Label(header_frame, text="监控视频存储计算器",style='Title.TLabel')title.pack()subtitle = ttk.Label(header_frame,text="专业的存储空间评估工具",style='Normal.TLabel')subtitle.pack()def create_forward_page(self):"""创建正向计算页面"""self.forward_frame = ttk.Frame(self.notebook, padding="20")self.notebook.add(self.forward_frame, text=" 计算存储需求 ")# 创建输入区域input_frame = ttk.LabelFrame(self.forward_frame, text="参数输入",padding="15")input_frame.pack(fill='x', padx=10, pady=5)# 添加输入控件self.create_input_field(input_frame, "摄像头数量:", 0, self.normal_font)self.cameras = self.entryself.create_input_field(input_frame, "每天录像时间(小时):", 1, self.normal_font)self.hours = self.entryself.hours.insert(0, "24") # 默认24小时self.create_input_field(input_frame, "需要保存的天数:", 2, self.normal_font)self.days = self.entry# 摄像头类型选择ttk.Label(input_frame, text="摄像头类型:", font=self.normal_font).grid(row=3, column=0, sticky=tk.W, pady=5)self.camera_type = ttk.Combobox(input_frame, width=25,font=self.normal_font)self.camera_type['values'] = ['200万像素', '300万像素', '400万像素', '500万像素']self.camera_type.current(0)self.camera_type.grid(row=3, column=1, sticky=tk.W, pady=5)# 编码方式选择ttk.Label(input_frame, text="编码方式:", font=self.normal_font).grid(row=4, column=0, sticky=tk.W, pady=5)self.encoding = ttk.Combobox(input_frame, width=25,font=self.normal_font)self.encoding['values'] = ['H.264', 'H.265']self.encoding.current(1) # 默认H.265self.encoding.grid(row=4, column=1, sticky=tk.W, pady=5)# 计算按钮btn_frame = ttk.Frame(self.forward_frame)btn_frame.pack(fill='x', pady=20)calc_btn = ttk.Button(btn_frame, text="计算存储需求",style='Custom.TButton',command=self.calculate_forward)calc_btn.pack(expand=True)# 结果显示区域self.forward_result_frame = ttk.LabelFrame(self.forward_frame,text="计算结果",padding="15",style='Result.TLabelframe')self.forward_result_frame.pack(fill='x', padx=10, pady=5)self.storage_label = ttk.Label(self.forward_result_frame,text="",font=self.result_font)self.storage_label.pack(anchor=tk.W)self.recommendation_label = ttk.Label(self.forward_result_frame,text="",font=self.result_font)self.recommendation_label.pack(anchor=tk.W)def create_reverse_page(self):"""创建反向计算页面"""self.reverse_frame = ttk.Frame(self.notebook, padding="20")self.notebook.add(self.reverse_frame, text=" 计算存储时间 ")# 创建输入区域input_frame = ttk.LabelFrame(self.reverse_frame,text="参数输入",padding="15")input_frame.pack(fill='x', padx=10, pady=5)# 添加输入控件self.create_input_field(input_frame, "硬盘容量(TB):", 0, self.normal_font)self.storage_size = self.entryself.create_input_field(input_frame, "摄像头数量:", 1, self.normal_font)self.rev_cameras = self.entryself.create_input_field(input_frame, "每天录像时间(小时):", 2, self.normal_font)self.rev_hours = self.entry# 摄像头类型选择ttk.Label(input_frame, text="摄像头类型:",font=self.normal_font).grid(row=3, column=0,sticky=tk.W, pady=5)self.rev_camera_type = ttk.Combobox(input_frame, width=25,font=self.normal_font)self.rev_camera_type['values'] = ['200万像素', '300万像素', '400万像素', '500万像素']self.rev_camera_type.current(0)self.rev_camera_type.grid(row=3, column=1, sticky=tk.W, pady=5)# 编码方式选择ttk.Label(input_frame, text="编码方式:",font=self.normal_font).grid(row=4, column=0,sticky=tk.W, pady=5)self.rev_encoding = ttk.Combobox(input_frame, width=25,font=self.normal_font)self.rev_encoding['values'] = ['H.264', 'H.265']self.rev_encoding.current(1) # 默认H.265self.rev_encoding.grid(row=4, column=1, sticky=tk.W, pady=5)# 计算按钮btn_frame = ttk.Frame(self.reverse_frame)btn_frame.pack(fill='x', pady=20)calc_btn = ttk.Button(btn_frame,text="计算可存储天数",style='Custom.TButton',command=self.calculate_reverse)calc_btn.pack(expand=True)# 结果显示区域self.reverse_result_frame = ttk.LabelFrame(self.reverse_frame,text="计算结果",padding="15",style='Result.TLabelframe')self.reverse_result_frame.pack(fill='x', padx=10, pady=5)self.days_label = ttk.Label(self.reverse_result_frame,text="",font=self.result_font)self.days_label.pack(anchor=tk.W)def create_footer(self):"""创建页脚"""footer = ttk.Label(self.root,text="© 2024 专业视频监控存储解决方案",style='Normal.TLabel')footer.pack(pady=10)def create_input_field(self, parent, label_text, row, font):"""创建统一的输入字段"""ttk.Label(parent, text=label_text,font=font).grid(row=row, column=0,sticky=tk.W, pady=5)self.entry = ttk.Entry(parent, width=25,font=font)self.entry.grid(row=row, column=1, sticky=tk.W, pady=5)return self.entrydef calculate_storage(self, cameras, hours_per_day, days, camera_type, encoding):"""计算存储需求camera_type: 摄像头类型 (200万/300万/400万/500万)encoding: 编码方式 (H.264/H.265)"""# 每天存储空间(GB)daily_storage = {'200万像素': {'H.264': 42.19, # 4096kbps'H.265': 21.09 # 2048kbps},'300万像素': {'H.264': 42.19, # 4096kbps'H.265': 21.09 # 2048kbps},'400万像素': {'H.264': 42.19, # 4096kbps'H.265': 21.09 # 2048kbps},'500万像素': {'H.264': 63.28, # 6144kbps'H.265': 31.64 # 3072kbps}}# 计算单个摄像头每天实际存储量daily_per_camera = daily_storage[camera_type][encoding] * (hours_per_day / 24)# 计算总存储量total_storage_gb = daily_per_camera * cameras * days# 转换为TB并返回return round(total_storage_gb / 1024, 2)def calculate_days(self, storage_tb, cameras, hours_per_day, camera_type, encoding):"""计算可存储天数"""daily_storage = {'200万像素': {'H.264': 42.19,'H.265': 21.09},'300万像素': {'H.264': 42.19,'H.265': 21.09},'400万像素': {'H.264': 42.19,'H.265': 21.09},'500万像素': {'H.264': 63.28,'H.265': 31.64}}# 计算单个摄像头每天实际存储量daily_per_camera = daily_storage[camera_type][encoding] * (hours_per_day / 24)# 计算可存储天数total_gb = storage_tb * 1024days = total_gb / (daily_per_camera * cameras)return round(days, 1)def calculate_forward(self):try:cameras = int(self.cameras.get())hours = float(self.hours.get())days = int(self.days.get())camera_type = self.camera_type.get()encoding = self.encoding.get()if cameras <= 0 or hours <= 0 or days <= 0:raise ValueError("请输入大于0的数值")# 获取单个摄像头每天的存储量daily_storage = {'200万像素': {'H.264': 42.19,'H.265': 21.09},'300万像素': {'H.264': 42.19,'H.265': 21.09},'400万像素': {'H.264': 42.19,'H.265': 21.09},'500万像素': {'H.264': 63.28,'H.265': 31.64}}daily_per_camera = daily_storage[camera_type][encoding] * (hours / 24)daily_total = daily_per_camera * camerasstorage = self.calculate_storage(cameras, hours, days, camera_type, encoding)self.storage_label.config(text=f"每天存储空间: {round(daily_total, 2)} GB/天\n"f"总存储容量: {storage} TB",foreground=self.colors['success'])self.recommendation_label.config(text=f"建议配置: {math.ceil(storage)} TB 硬盘\n"f"(基于{camera_type}摄像头,{encoding}编码)\n"f"单个摄像头: {round(daily_per_camera, 2)} GB/天",foreground=self.colors['success'])except ValueError as e:self.storage_label.config(text="输入错误!",foreground='red')self.recommendation_label.config(text="请检查输入的数值是否正确",foreground='red')def calculate_reverse(self):try:storage = float(self.storage_size.get())cameras = int(self.rev_cameras.get())hours = float(self.rev_hours.get())camera_type = self.rev_camera_type.get()encoding = self.rev_encoding.get()if storage <= 0 or cameras <= 0 or hours <= 0:raise ValueError("请输入大于0的数值")# 获取单个摄像头每天的存储量daily_storage = {'200万像素': {'H.264': 42.19,'H.265': 21.09},'300万像素': {'H.264': 42.19,'H.265': 21.09},'400万像素': {'H.264': 42.19,'H.265': 21.09},'500万像素': {'H.264': 63.28,'H.265': 31.64}}daily_per_camera = daily_storage[camera_type][encoding] * (hours / 24)daily_total = daily_per_camera * camerasdays = self.calculate_days(storage, cameras, hours, camera_type, encoding)self.days_label.config(text=f"每天存储空间: {round(daily_total, 2)} GB/天\n"f"单个摄像头: {round(daily_per_camera, 2)} GB/天\n"f"可存储天数: {days} 天\n"f"约等于 {round(days/30, 1)} 个月 或 {round(days/365, 1)} 年\n"f"(基于{camera_type}摄像头,{encoding}编码)",foreground=self.colors['success'])except ValueError as e:self.days_label.config(text="输入错误!\n请检查输入的数值是否正确",foreground='red')def main():root = tk.Tk()app = StorageCalculator(root)root.mainloop()if __name__ == "__main__":main()