找回密码
 立即注册
搜索
查看: 55|回复: 9

最近玩偷菜做的倒计时闹铃小工具

[复制链接]
灌水成绩
3
3
78
主题
帖子
积分

等级头衔 ID : 694
用户组 : 注册会员

积分成就 测量币 : 78
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 2026-4-17 14:22:00 来自手机 | 显示全部楼层 |阅读模式
任务条可以拖拽,看得到进度,
可以透明
https://wwbvp.lanzouu.com/iXP483ngisnc
密码:buon




代码如下:

import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import threading
import time
import json
import os
import sys
import winsound

# --- 解决打包后资源路径问题 ---
def resource_path(relative_path):
    """获取打包后资源的绝对路径"""
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

# --- 配置文件路径 (隐藏到系统AppData目录) ---
APP_DATA_DIR = os.path.join(os.environ['APPDATA'], "涂涂牌倒计时闹钟")
os.makedirs(APP_DATA_DIR, exist_ok=True)

CONFIG_FILE = os.path.join(APP_DATA_DIR, "countdown_tasks.json")
WINDOW_CONFIG_FILE = os.path.join(APP_DATA_DIR, "window_config.json")
ALARM_SOUND = resource_path("alarm.wav") # 闹钟声音文件路径

class CountdownTask:
    def __init__(self, name, total_seconds, remind_before=0):
        self.name = name
        self.total_seconds = total_seconds
        self.remaining = total_seconds
        self.remind_before = remind_before
        self.is_running = False
        self.is_finished = False
        self.reminded = False
        self.is_alarming = False

    def to_dict(self):
        return {
            "name": self.name,
            "total_seconds": self.total_seconds,
            "remaining": self.remaining,
            "remind_before": self.remind_before,
            "is_finished": self.is_finished
        }

    @staticmethod
    def from_dict(data):
        task = CountdownTask(data["name"], data["total_seconds"], data.get("remind_before", 0))
        task.remaining = data["remaining"]
        task.is_finished = data["is_finished"]
        return task

class App:
    def __init__(self, root):
        self.root = root
        self.root.title("涂涂牌倒计时闹钟")
        
        self.load_window_config()
        self.root.minsize(380, 300)
        
        self.tasks = []
        self.task_widgets = []
        self.breathing_state = 0
        self.breathing_colors = ["#ff3333", "#ff9999"]
        self.dragging_index = None
        
        self.load_data()
        self.setup_ui()
        
        self.running = True
        self.update_thread = threading.Thread(target=self.tick_loop, daemon=True)
        self.update_thread.start()
        
        self.breathing_loop()
        self.update_clock()
        
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)

    def setup_ui(self):
        frame_top = tk.Frame(self.root, pady=8, bg="#f0f0f0")
        frame_top.pack(fill='x', side='top')
        
        frame_top.grid_columnconfigure(2, weight=1)
        
        btn_group = tk.Frame(frame_top, bg="#f0f0f0")
        btn_group.grid(row=0, column=0, sticky='w', padx=10)
        
        btn_add = tk.Button(btn_group, text="➕ 新建", command=self.add_task_dialog,
                           bg="#4CAF50", fg="white", font=("Arial", 9, "bold"))
        btn_add.pack(side='left', padx=2)
        
        btn_pause_all = tk.Button(btn_group, text="⏸️ 全停", command=self.pause_all)
        btn_pause_all.pack(side='left', padx=2)
        
        btn_reset_all = tk.Button(btn_group, text="🔄 全重置", command=self.reset_all)
        btn_reset_all.pack(side='left', padx=2)
        
        btn_stop_all_alarm = tk.Button(btn_group, text="🔇 全静音", bg="red", fg="white",
                                      command=self.stop_all_alarm)
        btn_stop_all_alarm.pack(side='left', padx=2)

        setting_group = tk.Frame(frame_top, bg="#f0f0f0")
        setting_group.grid(row=0, column=3, sticky='e', padx=10)
        
        tk.Label(setting_group, text="透:", bg="#f0f0f0", font=("Arial", 9)).pack(side='left')
        self.alpha_slider = tk.Scale(setting_group, from_=20, to=100, orient='horizontal',
                                      length=60, showvalue=0, command=self.change_alpha)
        self.alpha_slider.set(100)
        self.alpha_slider.pack(side='left', padx=3)
        
        self.clock_label = tk.Label(setting_group, text="00:00:00",
                                   font=("Arial", 12, "bold"), fg="#2196F3", bg="#f0f0f0")
        self.clock_label.pack(side='left', padx=8)

        self.canvas = tk.Canvas(self.root, bg="white")
        self.scrollbar = ttk.Scrollbar(self.root, orient="vertical", command=self.canvas.yview)
        self.scrollable_frame = ttk.Frame(self.canvas)

        self.scrollable_frame.bind(
            "",
            lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all"))
        )

        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw", tags="frame")
        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        
        self.canvas.bind("", self.on_canvas_configure)
        self.canvas.bind_all("", self.on_mousewheel)

        self.canvas.pack(side="left", fill="both", expand=True)
        self.scrollbar.pack(side="right", fill="y")
        
        self.refresh_task_list()

    def on_mousewheel(self, event):
        self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")

    def on_canvas_configure(self, event):
        self.canvas.itemconfig("frame", width=event.width)

    def change_alpha(self, value):
        alpha_val = int(value) / 100.0
        self.root.attributes("-alpha", alpha_val)

    def update_clock(self):
        current_time = time.strftime("%H:%M:%S")
        self.clock_label.config(text=current_time)
        self.root.after(1000, self.update_clock)

    def add_task_dialog(self):
        win = tk.Toplevel(self.root)
        win.title("新建任务")
        win.geometry("350x300")
        win.resizable(False, False)
        win.transient(self.root)
        
        tk.Label(win, text="任务名称:", font=("Arial", 10)).pack(pady=5)
        name_entry = tk.Entry(win, font=("Arial", 12), width=25)
        name_entry.pack()
        name_entry.insert(0, "新任务")
        name_entry.focus_set()
        
        time_frame = tk.Frame(win)
        time_frame.pack(pady=10)
        
        tk.Label(time_frame, text="时:").grid(row=0, column=0)
        hour_entry = tk.Entry(time_frame, width=5)
        hour_entry.grid(row=0, column=1, padx=5)
        hour_entry.insert(0, "0")
        
        tk.Label(time_frame, text="分:").grid(row=0, column=2)
        min_entry = tk.Entry(time_frame, width=5)
        min_entry.grid(row=0, column=3, padx=5)
        min_entry.insert(0, "5")
        
        tk.Label(time_frame, text="秒:").grid(row=0, column=4)
        sec_entry = tk.Entry(time_frame, width=5)
        sec_entry.grid(row=0, column=5, padx=5)
        sec_entry.insert(0, "0")
        
        tk.Label(win, text="提前多少秒提醒:", font=("Arial", 10)).pack(pady=5)
        remind_entry = tk.Entry(win, font=("Arial", 12), width=10)
        remind_entry.pack()
        remind_entry.insert(0, "10")
        
        def confirm(event=None):
            try:
                name = name_entry.get()
                h = int(hour_entry.get() or 0)
                m = int(min_entry.get() or 0)
                s = int(sec_entry.get() or 0)
                remind_s = int(remind_entry.get() or 0)
               
                total_secs = h * 3600 + m * 60 + s
               
                if total_secs

重要声明:以上内容仅代表作者梦里的青蛙观点,不代表本站测量协会立场。如有涉及侵权请尽快告知,我们将会在第一时间处理。作者原创内容未经允许不得转载!

站长联系邮箱:1339305021@qq.com

站长联系微信:dddnnbbb

灌水成绩
0
17
24
主题
帖子
积分

等级头衔 ID : 802
用户组 : 新手上路

积分成就 测量币 : 24
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 6 天前 | 显示全部楼层
你说的偷菜跟我理解的是同一个吗
回复

使用道具 举报

灌水成绩
1
22
33
主题
帖子
积分

等级头衔 ID : 840
用户组 : 新手上路

积分成就 测量币 : 33
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 5 天前 | 显示全部楼层
呵呵,感觉又回到二十年前全民偷菜的时候。我现在播种了随缘,想起来就玩一下。如果定闹钟那估计又该晚上睡不着觉了
回复

使用道具 举报

灌水成绩
0
13
0
主题
帖子
积分

等级头衔 ID : 861
用户组 : 新手上路

积分成就 测量币 : 0
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 5 天前 | 显示全部楼层
没有自动化偷菜工具不好玩
回复

使用道具 举报

灌水成绩
2
20
33
主题
帖子
积分

等级头衔 ID : 862
用户组 : 新手上路

积分成就 测量币 : 33
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 5 天前 | 显示全部楼层
这个跟我用手机设闹钟有啥区别
回复

使用道具 举报

灌水成绩
3
30
43
主题
帖子
积分

等级头衔 ID : 817
用户组 : 新手上路

积分成就 测量币 : 43
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 5 天前 | 显示全部楼层
虽然用不到,也要点赞,感谢分享
回复

使用道具 举报

灌水成绩
2
19
46
主题
帖子
积分

等级头衔 ID : 852
用户组 : 新手上路

积分成就 测量币 : 46
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 5 天前 | 显示全部楼层
哈哈,感觉回到当年QQ空间的偷菜,停车位小游戏了
回复

使用道具 举报

灌水成绩
0
23
25
主题
帖子
积分

等级头衔 ID : 864
用户组 : 新手上路

积分成就 测量币 : 25
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 5 天前 | 显示全部楼层
现在怎么哪里还有偷菜的游戏吗
回复

使用道具 举报

灌水成绩
0
20
35
主题
帖子
积分

等级头衔 ID : 875
用户组 : 新手上路

积分成就 测量币 : 35
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 4 天前 | 显示全部楼层
微信小程序啊 最近玩得好友蛮多的
回复

使用道具 举报

灌水成绩
1
27
10
主题
帖子
积分

等级头衔 ID : 863
用户组 : 新手上路

积分成就 测量币 : 10
违规 : 0
在线时间 : 0 小时
注册时间 : 2026-4-6
最后登录 : 2026-4-23

勋章

活跃会员最佳新人

联系方式

发表于 4 天前 | 显示全部楼层
如果能隐藏面板,只留个倒计时就好了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|测量协会 ( 桂ICP备2026007449号-1 )

GMT+8, 2026-4-25 03:16 , Processed in 0.072868 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表