当前位置: 首页 > article >正文

时区转换工具

开发一个Python程序,将用户输入的北京日期时间转换为全球多个目标地区的对应时间,支持手动选择地区,并显示开始和结束两个时间段的转换结果

import pytz
from datetime import datetime
import pandas as pd
from tabulate import tabulate
import tkinter as tk
from tkinter import ttk, colorchooser, filedialog, messagebox
import tkinter.font as font
import json
import os
#from PIL import Image, ImageTk
from tkcalendar import DateEntry
import webbrowser

class TimeZoneConverter:
    def __init__(self):
        # 预定义常用时区映射表
        self.timezone_mapping = {
            "上海": "Asia/Shanghai",
            "纽约": "America/New_York",
            "伦敦": "Europe/London",
            "东京": "Asia/Tokyo",
            "悉尼": "Australia/Sydney",
            "巴黎": "Europe/Paris",
            "莫斯科": "Europe/Moscow",
            "迪拜": "Asia/Dubai",
            "洛杉矶": "America/Los_Angeles",
            "巴西(圣保罗)": "America/Sao_Paulo",
            "新德里": "Asia/Kolkata",
            "新加坡": "Asia/Singapore",
            "开普敦": "Africa/Johannesburg",
        }
    
    def add_timezone(self, name, timezone_str):
        """添加新的时区配置"""
        if timezone_str in pytz.all_timezones:
            self.timezone_mapping[name] = timezone_str
            return True
        else:
            print(f"错误: {timezone_str} 不是有效的时区标识符")
            return False
    
    def convert_time(self, beijing_time, target_timezone):
        """将北京时间转换为目标时区时间"""
        # 确保输入的是datetime对象
        if not isinstance(beijing_time, datetime):
            raise TypeError("时间必须是datetime对象")
        
        # 设置北京时区
        beijing_tz = pytz.timezone("Asia/Shanghai")
        beijing_time_with_tz = beijing_tz.localize(beijing_time)
        
        # 转换到目标时区
        target_tz = pytz.timezone(target_timezone)
        target_time = beijing_time_with_tz.astimezone(target_tz)
        
        return target_time
    
    def convert_time_range(self, start_time, end_time, target_timezones):
        """转换时间范围到多个目标时区"""
        results = []
        
        # 对每个目标时区进行转换
        for name, tz_str in target_timezones.items():
            start_converted = self.convert_time(start_time, tz_str)
            end_converted = self.convert_time(end_time, tz_str)
            
            results.append({
                "地区": name,
                "时区": tz_str,
                "开始时间": start_converted.strftime("%Y-%m-%d %H:%M"),
                "结束时间": end_converted.strftime("%Y-%m-%d %H:%M")
            })
        
        return results
    
    def display_results(self, results):
        """显示转换结果"""
        df = pd.DataFrame(results)
        print("\n时区转换结果:")
        print(tabulate(df, headers='keys', tablefmt='pretty', showindex=False))
    
    def get_available_timezones(self):
        """获取所有可用的时区名称"""
        return list(self.timezone_mapping.keys())

    def batch_convert(self, beijing_times, target_timezones):
        """批量转换多个北京时间到多个目标时区"""
        results = []
        
        for time_point in beijing_times:
            for name, tz_str in target_timezones.items():
                converted = self.convert_time(time_point, tz_str)
                results.append({
                    "原始北京时间": time_point.strftime("%Y-%m-%d %H:%M"),
                    "目标地区": name,
                    "时区": tz_str,
                    "转换后时间": converted.strftime("%Y-%m-%d %H:%M")
                })
        
        return results

    def calculate_time_difference(self, time1, time2, timezone1, timezone2):
        """计算两个不同时区时间点之间的时间差"""
        # 确保输入的是datetime对象
        if not isinstance(time1, datetime) or not isinstance(time2, datetime):
            raise TypeError("时间必须是datetime对象")
        
        # 设置时区
        tz1 = pytz.timezone(timezone1)
        tz2 = pytz.timezone(timezone2)
        
        time1_with_tz = tz1.localize(time1)
        time2_with_tz = tz2.localize(time2)
        
        # 计算时间差
        time_diff = time2_with_tz - time1_with_tz
        
        # 返回时间差(秒)
        return time_diff.total_seconds()


def parse_datetime(datetime_str):
    """解析用户输入的日期时间字符串"""
    try:
        return datetime.strptime(datetime_str, "%Y-%m-%d %H:%M")
    except ValueError:
        print("错误: 日期时间格式不正确,请使用 YYYY-MM-DD HH:MM 格式")
        return None


def main():
    converter = TimeZoneConverter()
    
    print("欢迎使用北京时区转换工具")
    print("请输入北京时间 (格式: YYYY-MM-DD HH:MM)")
    
    # 获取开始时间
    while True:
        start_time_str = input("开始时间: ")
        start_time = parse_datetime(start_time_str)
        if start_time:
            break
    
    # 获取结束时间
    while True:
        end_time_str = input("结束时间: ")
        end_time = parse_datetime(end_time_str)
        if end_time:
            if end_time < start_time:
                print("错误: 结束时间不能早于开始时间")
            else:
                break
    
    # 显示可用时区
    available_timezones = converter.get_available_timezones()
    print("\n可用的目标地区:")
    for i, tz in enumerate(available_timezones, 1):
        print(f"{i}. {tz}")
    
    # 选择目标时区
    selected_indices = input("\n请选择目标地区 (输入序号,多个序号用逗号分隔,输入'all'选择所有): ")
    
    selected_timezones = {}
    if selected_indices.lower() == 'all':
        selected_timezones = converter.timezone_mapping
    else:
        try:
            indices = [int(idx.strip()) for idx in selected_indices.split(',')]
            for idx in indices:
                if 1 <= idx <= len(available_timezones):
                    tz_name = available_timezones[idx-1]
                    selected_timezones[tz_name] = converter.timezone_mapping[tz_name]
                else:
                    print(f"警告: 序号 {idx} 超出范围,已忽略")
        except ValueError:
            print("警告: 输入格式不正确,将使用默认时区 (北京)")
            selected_timezones = {"北京": "Asia/Shanghai"}
    
    # 如果没有选择任何时区,使用默认值
    if not selected_timezones:
        print("未选择任何时区,将使用默认时区 (巴西)")
        selected_timezones = {"巴西": "America/Sao_Paulo"}
    
    # 执行转换
    results = converter.convert_time_range(start_time, end_time, selected_timezones)
    
    # 显示结果
    converter.display_results(results)


class Settings:
    def __init__(self):
        self.config_file = "timezone_converter_settings.json"
        self.default_settings = {
            "font_family": "Arial",
            "font_size": 10,
            "text_color": "#000000",
            "bg_color": "#f0f0f0",
            "bg_image": "",
            "version": "1.0.0"
        }
        self.settings = self.load_settings()
    
    def load_settings(self):
        """从文件加载设置"""
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except Exception as e:
                print(f"加载设置时出错: {e}")
                return self.default_settings.copy()
        else:
            return self.default_settings.copy()
    
    def save_settings(self):
        """保存设置到文件"""
        try:
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(self.settings, f, ensure_ascii=False, indent=4)
            return True
        except Exception as e:
            print(f"保存设置时出错: {e}")
            return False
    
    def get(self, key, default=None):
        """获取设置值"""
        return self.settings.get(key, default)
    
    def set(self, key, value):
        """设置值"""
        self.settings[key] = value
        return self.save_settings()
    
    def reset_to_default(self):
        """重置为默认设置"""
        self.settings = self.default_settings.copy()
        return self.save_settings()


class TimeZoneConverterGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("北京时区转换工具")
        self.root.geometry("900x700")
        
        self.converter = TimeZoneConverter()
        self.settings = Settings()
        
        # 加载设置
        self.load_ui_settings()
        
        # 创建菜单
        self.create_menu()
        
        # 创建界面组件
        self.create_widgets()
    
    def load_ui_settings(self):
        """加载UI设置并应用"""
        # 设置字体
        self.font_family = self.settings.get("font_family", "Arial")
        self.font_size = self.settings.get("font_size", 10)
        self.default_font = (self.font_family, self.font_size)
        self.header_font = (self.font_family, self.font_size + 6, "bold")
        
        # 设置颜色
        self.text_color = self.settings.get("text_color", "#000000")
        self.bg_color = self.settings.get("bg_color", "#f0f0f0")
        
        # 应用背景色
        self.root.configure(bg=self.bg_color)
        
        # 加载背景图片
        self.bg_image_path = self.settings.get("bg_image", "")
        self.bg_image = None
        self.bg_label = None
        
        if self.bg_image_path and os.path.exists(self.bg_image_path):
            self.load_background_image(self.bg_image_path)
    
    def load_background_image(self, image_path):
        """加载背景图片"""
        try:
            # 加载图片
            image = Image.open(image_path)
            
            # 调整图片大小以适应窗口
            window_width = self.root.winfo_width()
            window_height = self.root.winfo_height()
            
            # 如果窗口尚未渲染,使用几何尺寸
            if window_width <= 1:
                window_width = 900
                window_height = 700
            
            image = image.resize((window_width, window_height), Image.LANCZOS)
            
            # 转换为Tkinter可用的格式
            self.bg_image = ImageTk.PhotoImage(image)
            
            # 创建或更新背景标签
            if self.bg_label:
                self.bg_label.configure(image=self.bg_image)
            else:
                self.bg_label = tk.Label(self.root, image=self.bg_image)
                self.bg_label.place(x=0, y=0, relwidth=1, relheight=1)
                self.bg_label.lower()  # 将背景放到最底层
            
            # 更新设置
            self.settings.set("bg_image", image_path)
            
            return True
        except Exception as e:
            messagebox.showerror("错误", f"加载背景图片失败: {str(e)}")
            return False
    
    def create_menu(self):
        """创建菜单栏"""
        menubar = tk.Menu(self.root)
        
        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        file_menu.add_command(label="导出结果", command=self.export_results)
        file_menu.add_separator()
        file_menu.add_command(label="退出", command=self.root.quit)
        menubar.add_cascade(label="文件", menu=file_menu)
        
        # 设置菜单
        settings_menu = tk.Menu(menubar, tearoff=0)
        settings_menu.add_command(label="界面设置", command=self.open_settings)
        settings_menu.add_command(label="重置设置", command=self.reset_settings)
        menubar.add_cascade(label="设置", menu=settings_menu)
        
        # 帮助菜单
        help_menu = tk.Menu(menubar, tearoff=0)
        help_menu.add_command(label="使用说明", command=self.show_help)
        help_menu.add_command(label="关于", command=self.show_about)
        menubar.add_cascade(label="帮助", menu=help_menu)
        
        self.root.config(menu=menubar)
    
    def create_widgets(self):
        # 创建主框架
        self.main_frame = ttk.Frame(self.root)
        self.main_frame.pack(fill="both", expand=True, padx=20, pady=20)
        
        # 标题
        title_label = ttk.Label(self.main_frame, text="北京时区转换工具", font=self.header_font)
        title_label.pack(pady=10)
        
        # 输入框架
        input_frame = ttk.LabelFrame(self.main_frame, text="输入北京时间")
        input_frame.pack(fill="x", padx=10, pady=10)
        
        # 开始时间 - 使用日期选择器和时间滚动选择
        start_frame = ttk.Frame(input_frame)
        start_frame.pack(fill="x", padx=10, pady=5)
        
        ttk.Label(start_frame, text="开始日期:").pack(side="left", padx=5)
        self.start_date_entry = DateEntry(start_frame, width=12, background='darkblue',
                                         foreground='white', borderwidth=2, date_pattern='yyyy-mm-dd')
        self.start_date_entry.pack(side="left", padx=5)
        
        ttk.Label(start_frame, text="时间:").pack(side="left", padx=5)
        
        # 小时选择
        self.start_hour_var = tk.StringVar()
        self.start_hour_spinbox = ttk.Spinbox(start_frame, from_=0, to=23, width=2, 
                                             textvariable=self.start_hour_var, format="%02.0f")
        self.start_hour_spinbox.pack(side="left")
        self.start_hour_var.set("09")
        
        ttk.Label(start_frame, text=":").pack(side="left")
        
        # 分钟选择
        self.start_minute_var = tk.StringVar()
        self.start_minute_spinbox = ttk.Spinbox(start_frame, from_=0, to=59, width=2, 
                                               textvariable=self.start_minute_var, format="%02.0f")
        self.start_minute_spinbox.pack(side="left")
        self.start_minute_var.set("00")
        
        # 结束时间
        end_frame = ttk.Frame(input_frame)
        end_frame.pack(fill="x", padx=10, pady=5)
        
        ttk.Label(end_frame, text="结束日期:").pack(side="left", padx=5)
        self.end_date_entry = DateEntry(end_frame, width=12, background='darkblue',
                                       foreground='white', borderwidth=2, date_pattern='yyyy-mm-dd')
        self.end_date_entry.pack(side="left", padx=5)
        
        ttk.Label(end_frame, text="时间:").pack(side="left", padx=5)
        
        # 小时选择
        self.end_hour_var = tk.StringVar()
        self.end_hour_spinbox = ttk.Spinbox(end_frame, from_=0, to=23, width=2, 
                                           textvariable=self.end_hour_var, format="%02.0f")
        self.end_hour_spinbox.pack(side="left")
        self.end_hour_var.set("18")
        
        ttk.Label(end_frame, text=":").pack(side="left")
        
        # 分钟选择
        self.end_minute_var = tk.StringVar()
        self.end_minute_spinbox = ttk.Spinbox(end_frame, from_=0, to=59, width=2, 
                                             textvariable=self.end_minute_var, format="%02.0f")
        self.end_minute_spinbox.pack(side="left")
        self.end_minute_var.set("00")
        
        # 时区选择框架
        timezone_frame = ttk.LabelFrame(self.main_frame, text="选择目标时区")
        timezone_frame.pack(fill="both", expand=True, padx=10, pady=10)
        
        # 创建时区选择列表 - 使用Treeview替代Listbox以支持更好的滚动
        columns = ("时区名称",)
        self.timezone_tree = ttk.Treeview(timezone_frame, columns=columns, show="headings", selectmode="extended")
        self.timezone_tree.heading("时区名称", text="时区名称")
        self.timezone_tree.column("时区名称", width=150)
        self.timezone_tree.pack(side="left", fill="both", expand=True, padx=10, pady=10)
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(timezone_frame, orient="vertical", command=self.timezone_tree.yview)
        scrollbar.pack(side="right", fill="y", pady=10)
        self.timezone_tree.config(yscrollcommand=scrollbar.set)
        
        # 填充时区列表
        for tz in self.converter.get_available_timezones():
            self.timezone_tree.insert("", tk.END, values=(tz,))
        
        # 按钮框架
        button_frame = ttk.Frame(self.main_frame)
        button_frame.pack(fill="x", padx=10, pady=10)
        
        # 转换按钮
        convert_button = ttk.Button(button_frame, text="转换时区", command=self.convert)
        convert_button.pack(side="left", padx=10)
        
        # 全选按钮
        select_all_button = ttk.Button(button_frame, text="全选时区", command=self.select_all)
        select_all_button.pack(side="left", padx=10)
        
        # 清除选择按钮
        clear_button = ttk.Button(button_frame, text="清除选择", command=self.clear_selection)
        clear_button.pack(side="left", padx=10)
        
        # 结果框架
        result_frame = ttk.LabelFrame(self.main_frame, text="转换结果")
        result_frame.pack(fill="both", expand=True, padx=10, pady=10)
        
        # 创建表格
        columns = ("地区", "时区", "开始时间", "结束时间")
        self.result_tree = ttk.Treeview(result_frame, columns=columns, show="headings")
        
        # 设置列标题
        for col in columns:
            self.result_tree.heading(col, text=col)
            self.result_tree.column(col, width=100)
        
        self.result_tree.pack(side="left", fill="both", expand=True, padx=10, pady=10)
        
        # 添加结果表格的滚动条
        result_scrollbar = ttk.Scrollbar(result_frame, orient="vertical", command=self.result_tree.yview)
        result_scrollbar.pack(side="right", fill="y", pady=10)
        self.result_tree.config(yscrollcommand=result_scrollbar.set)
        
        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set(f"版本: {self.settings.get('version')} | 就绪")
        status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 绑定窗口大小变化事件,以调整背景图片
        self.root.bind("<Configure>", self.on_window_resize)
    
    def on_window_resize(self, event):
        """窗口大小变化时调整背景图片"""
        if self.bg_image_path and os.path.exists(self.bg_image_path):
            # 仅当窗口大小真正变化时才重新加载
            if event.widget == self.root and (event.width != self.root.winfo_width() or 
                                             event.height != self.root.winfo_height()):
                self.load_background_image(self.bg_image_path)
    
    def select_all(self):
        """全选所有时区"""
        for item in self.timezone_tree.get_children():
            self.timezone_tree.selection_add(item)
    
    def clear_selection(self):
        """清除所有选择"""
        self.timezone_tree.selection_remove(self.timezone_tree.get_children())
    
    def convert(self):
        """执行时区转换"""
        try:
            # 获取开始时间
            start_date = self.start_date_entry.get()
            start_hour = self.start_hour_var.get().zfill(2)
            start_minute = self.start_minute_var.get().zfill(2)
            start_datetime_str = f"{start_date} {start_hour}:{start_minute}"
            start_datetime = datetime.strptime(start_datetime_str, "%Y-%m-%d %H:%M")
            
            # 获取结束时间
            end_date = self.end_date_entry.get()
            end_hour = self.end_hour_var.get().zfill(2)
            end_minute = self.end_minute_var.get().zfill(2)
            end_datetime_str = f"{end_date} {end_hour}:{end_minute}"
            end_datetime = datetime.strptime(end_datetime_str, "%Y-%m-%d %H:%M")
            
            # 检查时间顺序
            if end_datetime < start_datetime:
                messagebox.showerror("错误", "结束时间不能早于开始时间")
                return
            
            # 获取选中的时区
            selected_items = self.timezone_tree.selection()
            if not selected_items:
                messagebox.showwarning("警告", "请至少选择一个目标时区")
                return
            
            # 构建选中的时区字典
            selected_timezones = {}
            for item in selected_items:
                tz_name = self.timezone_tree.item(item, "values")[0]
                selected_timezones[tz_name] = self.converter.timezone_mapping[tz_name]
            
            # 执行转换
            results = self.converter.convert_time_range(start_datetime, end_datetime, selected_timezones)
            
            # 清空现有结果
            for item in self.result_tree.get_children():
                self.result_tree.delete(item)
            
            # 显示结果
            for result in results:
                self.result_tree.insert("", tk.END, values=(
                    result["地区"],
                    result["时区"],
                    result["开始时间"],
                    result["结束时间"]
                ))
            
            # 更新状态栏
            self.status_var.set(f"版本: {self.settings.get('version')} | 转换完成: {len(results)}个结果")
            
        except ValueError as e:
            messagebox.showerror("输入错误", f"请检查日期和时间格式: {str(e)}")
        except Exception as e:
            messagebox.showerror("错误", f"发生错误: {str(e)}")
    
    def export_results(self):
        """导出结果到文件"""
        if not self.result_tree.get_children():
            messagebox.showinfo("提示", "没有可导出的结果")
            return
        
        file_path = filedialog.asksaveasfilename(
            defaultextension=".csv",
            filetypes=[("CSV文件", "*.csv"), ("Excel文件", "*.xlsx"), ("所有文件", "*.*")]
        )
        
        if not file_path:
            return
        
        try:
            # 收集结果数据
            results = []
            for item in self.result_tree.get_children():
                values = self.result_tree.item(item, "values")
                results.append({
                    "地区": values[0],
                    "时区": values[1],
                    "开始时间": values[2],
                    "结束时间": values[3]
                })
            
            # 创建DataFrame
            df = pd.DataFrame(results)
            
            # 根据文件扩展名导出
            if file_path.endswith('.csv'):
                df.to_csv(file_path, index=False, encoding='utf-8-sig')
            elif file_path.endswith('.xlsx'):
                df.to_excel(file_path, index=False)
            else:
                df.to_csv(file_path, index=False, encoding='utf-8-sig')
            
            messagebox.showinfo("成功", f"结果已成功导出到 {file_path}")
            
        except Exception as e:
            messagebox.showerror("导出错误", f"导出结果时出错: {str(e)}")
    
    def open_settings(self):
        """打开设置对话框"""
        settings_window = tk.Toplevel(self.root)
        settings_window.title("界面设置")
        settings_window.geometry("500x400")
        settings_window.resizable(False, False)
        settings_window.transient(self.root)  # 设置为主窗口的子窗口
        
        # 创建设置框架
        settings_frame = ttk.Frame(settings_window, padding=20)
        settings_frame.pack(fill="both", expand=True)
        
        # 字体设置
        font_frame = ttk.LabelFrame(settings_frame, text="字体设置")
        font_frame.pack(fill="x", padx=10, pady=10)
        
        # 字体选择
        ttk.Label(font_frame, text="字体:").grid(row=0, column=0, sticky="w", padx=5, pady=5)
        
        # 获取系统可用字体
        available_fonts = sorted(font.families())
        font_var = tk.StringVar(value=self.font_family)
        font_combo = ttk.Combobox(font_frame, textvariable=font_var, values=available_fonts, state="readonly")
        font_combo.grid(row=0, column=1, sticky="ew", padx=5, pady=5)
        
        # 字体大小
        ttk.Label(font_frame, text="字体大小:").grid(row=1, column=0, sticky="w", padx=5, pady=5)
        size_var = tk.IntVar(value=self.font_size)
        size_spinbox = ttk.Spinbox(font_frame, from_=8, to=24, textvariable=size_var, width=5)
        size_spinbox.grid(row=1, column=1, sticky="w", padx=5, pady=5)
        
        # 颜色设置
        color_frame = ttk.LabelFrame(settings_frame, text="颜色设置")
        color_frame.pack(fill="x", padx=10, pady=10)
        
        # 文本颜色
        ttk.Label(color_frame, text="文本颜色:").grid(row=0, column=0, sticky="w", padx=5, pady=5)
        text_color_var = tk.StringVar(value=self.text_color)
        text_color_entry = ttk.Entry(color_frame, textvariable=text_color_var, width=10)
        text_color_entry.grid(row=0, column=1, sticky="w", padx=5, pady=5)
        
        text_color_button = ttk.Button(color_frame, text="选择...", 
                                      command=lambda: self.choose_color(text_color_var))
        text_color_button.grid(row=0, column=2, padx=5, pady=5)
        
        # 背景颜色
        ttk.Label(color_frame, text="背景颜色:").grid(row=1, column=0, sticky="w", padx=5, pady=5)
        bg_color_var = tk.StringVar(value=self.bg_color)
        bg_color_entry = ttk.Entry(color_frame, textvariable=bg_color_var, width=10)
        bg_color_entry.grid(row=1, column=1, sticky="w", padx=5, pady=5)
        
        bg_color_button = ttk.Button(color_frame, text="选择...", 
                                    command=lambda: self.choose_color(bg_color_var))
        bg_color_button.grid(row=1, column=2, padx=5, pady=5)
        
        # 背景图片设置
        bg_frame = ttk.LabelFrame(settings_frame, text="背景图片")
        bg_frame.pack(fill="x", padx=10, pady=10)
        
        bg_path_var = tk.StringVar(value=self.bg_image_path)
        bg_path_entry = ttk.Entry(bg_frame, textvariable=bg_path_var, width=30)
        bg_path_entry.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        
        bg_browse_button = ttk.Button(bg_frame, text="浏览...", 
                                     command=lambda: self.browse_bg_image(bg_path_var))
        bg_browse_button.grid(row=0, column=1, padx=5, pady=5)
        
        bg_clear_button = ttk.Button(bg_frame, text="清除", 
                                    command=lambda: bg_path_var.set(""))
        bg_clear_button.grid(row=0, column=2, padx=5, pady=5)
        
        # 按钮框架
        button_frame = ttk.Frame(settings_frame)
        button_frame.pack(fill="x", padx=10, pady=20)
        
        # 保存按钮
        save_button = ttk.Button(button_frame, text="保存设置", 
                                command=lambda: self.save_ui_settings(
                                    font_var.get(), size_var.get(), 
                                    text_color_var.get(), bg_color_var.get(),
                                    bg_path_var.get(), settings_window))
        save_button.pack(side="right", padx=5)
        
        # 取消按钮
        cancel_button = ttk.Button(button_frame, text="取消", 
                                  command=settings_window.destroy)
        cancel_button.pack(side="right", padx=5)
        
        # 使对话框模态
        settings_window.grab_set()
        settings_window.focus_set()
        settings_window.wait_window()
    
    def choose_color(self, color_var):
        """打开颜色选择器"""
        color = colorchooser.askcolor(color_var.get())[1]
        if color:
            color_var.set(color)
    
    def browse_bg_image(self, path_var):
        """浏览选择背景图片"""
        file_path = filedialog.askopenfilename(
            filetypes=[("图片文件", "*.png *.jpg *.jpeg *.gif *.bmp"), ("所有文件", "*.*")]
        )
        if file_path:
            path_var.set(file_path)
    
    def save_ui_settings(self, font_family, font_size, text_color, bg_color, bg_image, dialog):
        """保存UI设置并应用"""
        # 保存设置
        self.settings.set("font_family", font_family)
        self.settings.set("font_size", font_size)
        self.settings.set("text_color", text_color)
        self.settings.set("bg_color", bg_color)
        self.settings.set("bg_image", bg_image)
        
        # 应用设置
        self.font_family = font_family
        self.font_size = font_size
        self.default_font = (self.font_family, self.font_size)
        self.header_font = (self.font_family, self.font_size + 6, "bold")
        self.text_color = text_color
        self.bg_color = bg_color
        
        # 应用背景色
        self.root.configure(bg=self.bg_color)
        
        # 加载背景图片
        self.bg_image_path = bg_image
        if bg_image and os.path.exists(bg_image):
            self.load_background_image(bg_image)
        elif not bg_image and self.bg_label:
            self.bg_label.destroy()
            self.bg_label = None
            self.bg_image = None
        
        # 关闭对话框
        dialog.destroy()
        
        # 提示用户
        messagebox.showinfo("设置已保存", "界面设置已保存并应用")

    def reset_settings(self):
        """重置为默认设置"""
        if messagebox.askyesno("确认", "确定要重置所有设置到默认值吗?"):
            self.settings.reset_to_default()
            messagebox.showinfo("成功", "设置已重置为默认值,重启应用后生效")

    def show_help(self):
        """显示使用说明"""
        help_text = """
        北京时区转换工具使用说明:
        
        1. 输入北京时间:
            - 选择开始日期和时间
            - 选择结束日期和时间
        
        2. 选择目标时区:
            - 在列表中选择一个或多个目标时区
            - 可以使用"全选时区"按钮选择所有时区
            - 可以使用"清除选择"按钮取消所有选择
        
        3. 点击"转换时区"按钮执行转换
        
        4. 在结果表格中查看转换后的时间
        
        5. 可以使用"导出结果"功能将结果保存为CSV或Excel文件
        
        6. 在"设置"菜单中可以自定义界面外观
        """
        
        help_window = tk.Toplevel(self.root)
        help_window.title("使用说明")
        help_window.geometry("600x400")
        help_window.transient(self.root)
        
        text_widget = tk.Text(help_window, wrap="word", padx=10, pady=10)
        text_widget.pack(fill="both", expand=True)
        text_widget.insert("1.0", help_text)
        text_widget.config(state="disabled")
        
        scrollbar = ttk.Scrollbar(text_widget, command=text_widget.yview)
        scrollbar.pack(side="right", fill="y")
        text_widget.config(yscrollcommand=scrollbar.set)
        
        close_button = ttk.Button(help_window, text="关闭", command=help_window.destroy)
        close_button.pack(pady=10)
        
        help_window.grab_set()
        help_window.focus_set()

    def show_about(self):
        """显示关于信息"""
        version = self.settings.get("version", "1.0.0.0")
        about_text = f"""
        北京时区转换工具
        
        版本: {version}
        
        功能:
        - 将北京时间转换为全球多个时区的时间
        - 支持时间段转换
        - 自定义界面外观
        - 结果导出功能
        
          时区转换工具
        """
        
        messagebox.showinfo("关于", about_text)


def run_gui():
    root = tk.Tk()
    app = TimeZoneConverterGUI(root)
    root.mainloop()


if __name__ == "__main__":
    run_gui()

在这里插入图片描述


http://www.kler.cn/a/589449.html

相关文章:

  • X86 RouterOS 7.18 设置笔记六:端口映射(IPv4、IPv6)及回流问题
  • 无SIM卡时代即将来临?eSIM才是智联未来?
  • 一键批量txt转DWG,DWG转txt——插件实现 CAD c#二次开发
  • 基于Flask的东方财富网股票数据可视化分析系统
  • 基于python的图书馆书目推荐数据分析与可视化-django+spider+vue
  • 直击行业痛点,赛逸展2025科技创新奖推陈出新
  • Flutter_学习记录_ ImagePicker拍照、录制视频、相册选择照片和视频、上传文件
  • PHP:从入门到进阶的编程之旅
  • 语言大模型的模型微调方法LoRA
  • Linux进程状态详解:僵尸进程与孤儿进程的深度探索与实践
  • idea如何新建springboot项目
  • OpenManus:无需邀请码的开源版Manus,开启自动化新纪元
  • 2024山东大学计算机复试上机真题
  • 50个常用的DeepSeek提示词
  • linux环境下快速输出电脑的系统/硬件/显卡/网络/已安装软件等信息
  • 查看IP地址/Ping 命令
  • 学习threejs,使用MeshLambertMaterial漫反射材质
  • 微服务》》Kubernetes (K8S)安装
  • 网络安全和文档的关系
  • 【学习笔记】GPT系列模型演变过程