计时器

我用AI搓了一个没什么卵用的计时器

大概就是这样,选择开始时间和结束时间,这两个时间必须在现在日期的前后,第一次使用的时候要注意保存,点击“另存为”保存配置文件,在下一次进入的时候就可以直接运行了。还要注意,在运行前要在电脑终端下载依赖库

pip install tkcalendar

这是一个源文件地址,下载即用:https://47.122.22.218:29439/down/OHRRXX8MilE9.py

源码

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from datetime import datetime, timedelta
from tkcalendar import Calendar
import json
import os
import sys
import atexit

class UltimateTimeProgressApp:
    def __init__(self):
        # 初始化主窗口
        self.root = tk.Tk()
        self.root.title("时间进度大江浩版")
        self.root.geometry("900x450")
        self.root.minsize(800, 400)
        
        # 样式初始化
        self.setup_styles()
        
        # 核心变量
        self.preset_var = tk.StringVar(value="month")
        self.is_running = False
        self.last_config_path = None
        
        # 构建界面
        self.setup_main_frame()
        self.setup_sidebar()
        self.setup_main_content()
        
        # 文件管理
        self.app_data_path = self.get_app_data_dir()
        os.makedirs(self.app_data_path, exist_ok=True)
        self.load_last_config()
        
        # 注册退出处理
        atexit.register(self.cleanup_resources)
        self.root.protocol("WM_DELETE_WINDOW", self.graceful_exit)
        self.root.mainloop()

    def get_app_data_dir(self):
        """获取跨平台应用数据目录"""
        if sys.platform == 'win32':
            return os.path.join(os.environ['APPDATA'], 'TimeProgress')
        return os.path.join(os.path.expanduser('~'), '.config', 'TimeProgress')

    def setup_styles(self):
        """现代化样式配置"""
        style = ttk.Style()
        style.theme_use('clam')
        style.configure('TFrame', background='#F5F5F5')
        style.configure('TLabel', background='#F5F5F5', foreground='#333333')
        style.configure('TButton', font=('Segoe UI', 10), padding=6)
        style.configure('Title.TLabel', font=('Segoe UI', 12, 'bold'))
        style.configure('Progress.Horizontal.TProgressbar',
                      troughcolor='#EEEEEE',
                      background='#4A90E2',
                      thickness=25)

    def setup_main_frame(self):
        """主框架布局"""
        self.main_frame = ttk.Frame(self.root)
        self.main_frame.pack(fill=tk.BOTH, expand=True)

    def setup_sidebar(self):
        """左侧导航面板"""
        sidebar = ttk.Frame(self.main_frame, width=220)
        sidebar.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)
        
        ttk.Label(sidebar, text="时间预设", style='Title.TLabel').pack(pady=15)
        presets = [
            ('本周', 'week'),
            ('本月', 'month'),
            ('本季度', 'quarter'),
            ('本年', 'year'),
            ('自定义', 'custom')
        ]
        for text, val in presets:
            rb = ttk.Radiobutton(sidebar, text=text, variable=self.preset_var,
                                value=val, command=self.update_preset)
            rb.pack(anchor=tk.W, pady=3, padx=5)

    def setup_main_content(self):
        """主内容区域"""
        content = ttk.Frame(self.main_frame)
        content.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 时间选择区域
        time_frame = ttk.Frame(content)
        time_frame.pack(fill=tk.X, pady=15)
        self.start_entry = self.create_date_picker(time_frame, "开始时间", 'start')
        self.end_entry = self.create_date_picker(time_frame, "结束时间", 'end')
        
        # 控制按钮
        btn_frame = ttk.Frame(content)
        btn_frame.pack(fill=tk.X, pady=15)
        ttk.Button(btn_frame, text="▶ 启动/暂停", command=self.toggle_progress).pack(side=tk.LEFT)
        ttk.Button(btn_frame, text="📂 打开配置", command=self.load_config_dialog).pack(side=tk.LEFT, padx=10)
        ttk.Button(btn_frame, text="💾 另存为", command=self.save_config_dialog).pack(side=tk.LEFT)
        
        # 进度显示
        self.progress = ttk.Progressbar(content, style='Progress.Horizontal.TProgressbar')
        self.progress.pack(fill=tk.X, pady=20)
        
        # 状态信息
        status_frame = ttk.Frame(content)
        status_frame.pack(fill=tk.X)
        self.percent_var = tk.StringVar(value="0.000000%")
        ttk.Label(status_frame, textvariable=self.percent_var, font=('Consolas', 14)).pack(side=tk.LEFT)
        self.time_remaining_var = tk.StringVar(value="准备就绪")
        ttk.Label(status_frame, textvariable=self.time_remaining_var).pack(side=tk.RIGHT)

    def create_date_picker(self, parent, label_text, entry_type):
        """创建日期选择组件"""
        frame = ttk.Frame(parent)
        frame.pack(fill=tk.X, pady=8)
        
        ttk.Label(frame, text=label_text, width=8).pack(side=tk.LEFT)
        entry = ttk.Entry(frame, width=24)
        entry.pack(side=tk.LEFT, padx=5)
        ttk.Button(frame, text="📅 选择", 
                 command=lambda: self.show_calendar(entry_type)).pack(side=tk.LEFT)
        return entry

    def show_calendar(self, entry_type):
        """显示日历选择窗口"""
        top = tk.Toplevel(self.root)
        top.grab_set()
        top.title("选择日期")
        
        cal = Calendar(top, selectmode='day', date_pattern='yyyy-mm-dd')
        cal.pack(padx=20, pady=20)
        
        ttk.Button(top, text="确认", 
                 command=lambda: self.update_entry(entry_type, cal, top)).pack(pady=10)

    def update_entry(self, entry_type, calendar, window):
        """更新输入框内容"""
        date_str = calendar.get_date()
        time_part = "00:00:00" if entry_type == 'start' else "23:59:59"
        full_date = f"{date_str} {time_part}"
        
        target_entry = self.start_entry if entry_type == 'start' else self.end_entry
        target_entry.delete(0, tk.END)
        target_entry.insert(0, full_date)
        self.preset_var.set('custom')
        window.destroy()

    def update_preset(self):
        """处理预设选项变更"""
        preset = self.preset_var.get()
        now = datetime.now()
        
        if preset == 'week':
            start = now - timedelta(days=now.weekday())
        elif preset == 'month':
            start = now.replace(day=1)
        elif preset == 'quarter':
            quarter_month = ((now.month - 1) // 3) * 3 + 1
            start = now.replace(month=quarter_month, day=1)
        elif preset == 'year':
            start = now.replace(month=1, day=1)
        else:
            return
        
        self.start_entry.delete(0, tk.END)
        self.start_entry.insert(0, start.strftime("%Y-%m-%d 00:00:00"))
        self.end_entry.delete(0, tk.END)
        self.end_entry.insert(0, now.strftime("%Y-%m-%d 23:59:59"))

    def toggle_progress(self):
        """切换监控状态"""
        self.is_running = not self.is_running
        if self.is_running:
            self.start_progress()
        else:
            self.time_remaining_var.set("已暂停")

    def start_progress(self):
        """开始进度计算"""
        try:
            start = datetime.strptime(self.start_entry.get(), "%Y-%m-%d %H:%M:%S")
            end = datetime.strptime(self.end_entry.get(), "%Y-%m-%d %H:%M:%S")
            
            if end <= start:
                raise ValueError("结束时间必须晚于开始时间")
            
            self.total_seconds = (end - start).total_seconds()
            self.update_progress()
        except Exception as e:
            messagebox.showerror("配置错误", f"无效的时间设置:\n{str(e)}")
            self.is_running = False

    def update_progress(self):
        """更新进度显示"""
        if not self.is_running:
            return
        
        current = datetime.now()
        start = datetime.strptime(self.start_entry.get(), "%Y-%m-%d %H:%M:%S")
        elapsed = (current - start).total_seconds()
        
        if elapsed < 0:
            self.percent_var.set("0.000000%")
            self.time_remaining_var.set("未开始")
        elif elapsed >= self.total_seconds:
            self.percent_var.set("100.000000%")
            self.time_remaining_var.set("已完成")
            self.is_running = False
        else:
            percent = (elapsed / self.total_seconds) * 100
            remaining = self.total_seconds - elapsed
            
            self.progress['value'] = percent
            self.percent_var.set(f"{percent:.6f}%")
            self.time_remaining_var.set(self.format_timedelta(remaining))
        
        if self.is_running:
            self.root.after(1000, self.update_progress)

    def format_timedelta(self, seconds):
        """格式化剩余时间"""
        days, rem = divmod(seconds, 86400)
        hours, rem = divmod(rem, 3600)
        minutes, sec = divmod(rem, 60)
        return f"剩余:{int(days)}天 {int(hours):02}:{int(minutes):02}:{int(sec):02}"

    def save_config_dialog(self):
        """保存配置对话框"""
        filepath = filedialog.asksaveasfilename(
            title="保存配置文件",
            defaultextension=".json",
            filetypes=[("JSON 配置", "*.json"), ("所有文件", "*.*")],
            initialdir=self.app_data_path,
            initialfile="time_config.json"
        )
        if not filepath:
            return
        
        config = {
            'start': self.start_entry.get(),
            'end': self.end_entry.get(),
            'preset': self.preset_var.get(),
            'window_geometry': self.root.geometry(),
            'saved_at': datetime.now().isoformat()
        }
        
        try:
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(config, f, indent=2, ensure_ascii=False)
            self.last_config_path = filepath
            messagebox.showinfo("保存成功", f"配置已保存到:\n{filepath}")
        except Exception as e:
            messagebox.showerror("保存失败", f"保存文件失败:\n{str(e)}")

    def load_config_dialog(self):
        """加载配置对话框"""
        filepath = filedialog.askopenfilename(
            title="选择配置文件",
            filetypes=[("JSON 配置", "*.json"), ("所有文件", "*.*")],
            initialdir=self.app_data_path
        )
        if filepath:
            self.load_config_file(filepath)

    def load_config_file(self, filepath):
        """加载配置文件"""
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                config = json.load(f)
            
            # 恢复窗口尺寸
            if 'window_geometry' in config:
                self.root.geometry(config['window_geometry'])
            
            # 恢复时间设置
            self.start_entry.delete(0, tk.END)
            self.start_entry.insert(0, config.get('start', ''))
            self.end_entry.delete(0, tk.END)
            self.end_entry.insert(0, config.get('end', ''))
            
            # 恢复预设状态
            self.preset_var.set(config.get('preset', 'custom'))
            
            self.last_config_path = filepath
            messagebox.showinfo("加载成功", f"已加载配置:{os.path.basename(filepath)}")
            
        except json.JSONDecodeError:
            messagebox.showerror("配置错误", "文件格式无效,请选择正确的配置文件")
        except Exception as e:
            messagebox.showerror("加载失败", f"无法读取文件:\n{str(e)}")

    def load_last_config(self):
        """自动加载上次配置"""
        last_config = os.path.join(self.app_data_path, 'last_config.json')
        if os.path.exists(last_config):
            try:
                with open(last_config, 'r') as f:
                    config = json.load(f)
                    if config.get('last_path'):
                        self.load_config_file(config['last_path'])
            except:
                self.set_default_times()
        else:
            self.set_default_times()

    def set_default_times(self):
        """设置默认时间范围"""
        now = datetime.now()
        self.start_entry.insert(0, now.replace(hour=0, minute=0, second=0).strftime("%Y-%m-%d %H:%M:%S"))
        self.end_entry.insert(0, now.replace(hour=23, minute=59, second=59).strftime("%Y-%m-%d %H:%M:%S"))

    def graceful_exit(self):
        """优雅退出程序"""
        if messagebox.askokcancel("退出", "确定要退出程序吗?"):
            # 保存最后使用的配置路径
            if self.last_config_path:
                with open(os.path.join(self.app_data_path, 'last_config.json'), 'w') as f:
                    json.dump({'last_path': self.last_config_path}, f)
            self.root.destroy()

    def cleanup_resources(self):
        """清理系统资源"""
        pass

if __name__ == "__main__":
    try:
        UltimateTimeProgressApp()
    except Exception as e:
        messagebox.showerror("启动失败", f"程序初始化失败:\n{str(e)}")
暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇