当前位置:首页>python>【上班摸鱼小程序】附python代码

【上班摸鱼小程序】附python代码

  • 2026-10-11 06:30:43
【上班摸鱼小程序】附python代码
对多数人来说,上班是较为无聊的,而周末和节假日是快乐的。
针对这个现象,本程序设计了实时的下班倒计时、下一次节假日倒计时、周末倒计时功能。如下:
如果需要加班,可以点击左下角设置按钮,修改下班时间。程序默认17:00下班。
如果坐班实在过于无聊,可以点击右侧猫猫图,进入摸鱼小游戏界面。
首先会展示小游戏的中心思想:正入万山圈子里,一山放过一山拦。
长按空格键蓄力跳跃(出现蓄力条),控制白色方块依次跳过淡黑色平台。
跳出右侧界面,则挑战成功,展示提示语:穿尽千山与万水,始知天地本来宽。如下:
如果不幸掉入深渊,或者撞到平台侧面,则挑战失败,展示失败提示语:万物皆生,唯你独枯。茫茫天地间,竟全然无你托身之所……按R重试,按T退出。如下:
节假日倒计时功能的法定节假日包括元旦、春节、清明、劳动,端午、国庆、中秋。传统节日需从农历换算到洋历。
猫猫图分享如下:
完整代码如下:
import tkinter as tkfrom tkinter import messageboxfrom datetime import datetime, timedelta import os import tkinter.font as tkFont from zhdate import ZhDateimport randomDEFAULT_OFF_WORK_TIME = "17:00:00"off_work_time_str = DEFAULT_OFF_WORK_TIMEBG_COLOR       = "#000000"FG_COLOR       = "#cccccc"TITLE_COLOR    = "#ffffff"ACCENT_RED     = "#ff6b6b"ACCENT_CYAN    = "#ff6b6b"ACCENT_YELLOW  = "#ff6b6b"BUTTON_COLOR   = "#333333"BUTTON_TEXT    = "white"POPUP_BG       = "#1a1a1a"MASK_COLOR     = "#0a0a0a"CAT_IMAGE_PATH = r"E:\Bil大业\ELSE\下班\Cat.png" def get_next_holiday_info():    now = datetime.now()    current_year = now.year     spring_festival = ZhDate(current_year, 1, 1).to_datetime()    dragon_boat = ZhDate(current_year, 5, 5).to_datetime()    mid_autumn = ZhDate(current_year, 8, 15).to_datetime()    qingming = datetime(current_year, 4, 4)    holidays = [        (datetime(current_year, 1, 1), "元旦"),        (spring_festival, "春节"),        (qingming, "清明节"),        (datetime(current_year, 5, 1), "劳动节"),        (dragon_boat, "端午节"),        (datetime(current_year, 10, 1), "国庆节"),        (mid_autumn, "中秋节"),    ]    min_diff = None     next_holiday_name = ""    for year_offset in [0, 1]:        year = current_year + year_offset         for holiday_date, name in holidays:            if name == "元旦":                date_obj = datetime(year, 1, 1)            elif name == "春节":                date_obj = ZhDate(year, 1, 1).to_datetime()            elif name == "清明节":                date_obj = datetime(year, 4, 4)            elif name == "劳动节":                date_obj = datetime(year, 5, 1)            elif name == "端午节":                date_obj = ZhDate(year, 5, 5).to_datetime()            elif name == "国庆节":                date_obj = datetime(year, 10, 1)            elif name == "中秋节":                date_obj = ZhDate(year, 8, 15).to_datetime()            else:                continue             if date_obj > now:                diff = date_obj - now                 days = diff.days                 if min_diff is None or days < min_diff:                    min_diff = days                     next_holiday_name = name     if min_diff is not None:        return min_diff, next_holiday_name     return 0, "暂无数据"def calculate_time_diff(target_time_str):    now = datetime.now()    try:        h, m, s = map(int, target_time_str.split(':'))        target_time_today = now.replace(hour=h, minute=m, second=s, microsecond=0)    except ValueError:        return "时间格式错误", ACCENT_RED     if now >= target_time_today:        return "已经下班啦!", ACCENT_RED     delta = target_time_today - now     total_seconds = int(delta.total_seconds())    hours, remainder = divmod(total_seconds, 3600)    minutes, seconds = divmod(remainder, 60)    return f"{hours:02d}时{minutes:02d}分{seconds:02d}秒", ACCENT_RED def get_weekend_diff(target_time_str):    now = datetime.now()    weekday = now.weekday()    if weekday >= 5:        return "现在就是周末哦~", ACCENT_CYAN     try:        h, m, s = map(int, target_time_str.split(':'))    except ValueError:        return "时间格式错误", ACCENT_CYAN     if weekday == 4:        target = now.replace(hour=h, minute=m, second=s, microsecond=0)        delta = target - now         total_seconds = int(delta.total_seconds())        if total_seconds < 0:            return "周末已开始~", ACCENT_CYAN         hours, remainder = divmod(total_seconds, 3600)        minutes, seconds = divmod(remainder, 60)        return f"{hours}小时{minutes}分{seconds}秒", ACCENT_CYAN     else:        days_to_friday = 4 - weekday         target = now + timedelta(days=days_to_friday)        target = target.replace(hour=h, minute=m, second=s, microsecond=0)        delta = target - now         return f"{delta.days}天", ACCENT_CYAN class RoundedButton(tk.Canvas):    def __init__(self, parent, text, command=None, radius=3,                 bg=BUTTON_COLOR, fg="white", font=("arial", 11)):         tmp_font = tk.font.Font(family="arial", size=11)        text_w = tmp_font.measure(text)        w = text_w + 50         h = 40         super().__init__(parent, width=w, height=h,                         bg=parent["bg"], highlightthickness=0, cursor="hand2")        self.command = command         self.radius = radius         self.bg = bg         self.fg = fg         self.text = text         self.font = font         self._hover = False         self._draw()        self.bind("<Button-1>", lambda e: self.command() if self.command else None)        self.bind("<Enter>", lambda e: self._set_hover(True))        self.bind("<Leave>", lambda e: self._set_hover(False))    def _draw(self):        self.delete("all")        w = self.winfo_reqwidth()        h = self.winfo_reqheight()        r = self.radius         color = "#454545" if self._hover else self.bg         self.create_oval(0, 0, 2*r, 2*r, fill=color, outline=color)        self.create_oval(w-2*r, 0, w, 2*r, fill=color, outline=color)        self.create_oval(0, h-2*r, 2*r, h, fill=color, outline=color)        self.create_oval(w-2*r, h-2*r, w, h, fill=color, outline=color)        self.create_rectangle(r, 0, w-r, h, fill=color, outline=color)        self.create_rectangle(0, r, w, h-r, fill=color, outline=color)        self.create_text(w/2, h/2, text=self.text, fill=self.fg, font=self.font)    def _set_hover(self, hover):        self._hover = hover         self._draw()def create_rounded_image(image_path, size, radius=10):    try:        from PIL import Image, ImageDraw, ImageTk        img = Image.open(image_path).convert("RGBA")        img = img.resize(size, Image.LANCZOS)        mask = Image.new('L', size, 0)        draw = ImageDraw.Draw(mask)        draw.rounded_rectangle([(0, 0), size], radius=radius, fill=255)        result = Image.new('RGBA', size, (0, 0, 0, 0))        result.paste(img, (0, 0), mask)        return ImageTk.PhotoImage(result)    except ImportError:        return None    except Exception as e:        print(f"图片处理错误: {e}")        return Noneclass MiniGameApp:    def __init__(self, parent):        self.top = tk.Toplevel(parent)        self.top.title("摸鱼小游戏")        self.top.geometry("1200x500")         self.top.configure(bg="black")        self.top.resizable(False, False)        self.canvas = tk.Canvas(self.top, width=1200, height=500, bg="black", highlightthickness=0)        self.canvas.pack()        self.top.bind("<KeyPress>", self.on_key_press)        self.top.bind("<KeyRelease>", self.on_key_release)        self.top.bind("<r>", self.restart_game)        self.top.bind("<t>", self.close_game)        self.top.bind("<R>", self.restart_game)        self.top.bind("<T>", self.close_game)        self.GRAVITY = 0.8        self.MAX_CHARGE = 22         self.CHARGE_RATE = 0.4         self.player = {'x': 0, 'y': 0, 'w': 20, 'h': 20, 'vx': 0, 'vy': 0}        self.platforms = []        self.is_charging = False         self.charge_power = 0        self.game_over = False        self.game_won = False        self.game_state = 'playing'        self.text_fade = 0.0        self.reset_game()        self.game_loop()    def generate_platforms(self):        self.platforms = []        current_x = 0        self.platforms.append({'x': 0, 'y': 350, 'w': 120, 'h': 50})        current_x = 120         while current_x < 1200:            gap = random.randint(80, 160)            width = random.randint(60, 100)            next_y = random.randint(280, 360)            self.platforms.append({                'x': current_x + gap,                'y': next_y,                'w': width,                'h': 500 - next_y            })            current_x += gap + width    def reset_game(self):        self.generate_platforms()        start_plat = self.platforms[0]        self.player['x'] = start_plat['x'] + 10        self.player['y'] = start_plat['y'] - self.player['h']        self.player['vx'] = 0        self.player['vy'] = 0         self.game_over = False        self.game_won = False         self.is_charging = False         self.charge_power = 0        self.game_state = 'playing'        self.text_fade = 0.0        self.draw()    def on_key_press(self, event):        if event.keysym == 'space' and not self.game_over and not self.game_won:            self.is_charging = True    def on_key_release(self, event):        if event.keysym == 'space' and self.is_charging:            self.jump()            self.is_charging = False             self.charge_power = 0    def jump(self):        self.player['vx'] = 5 + (self.charge_power * 0.6)        self.player['vy'] = -(7 + (self.charge_power * 0.6))    def _get_faded_color(self, target_color_hex, progress):        if not target_color_hex.startswith('#'):            color_map = {                "red": (255, 0, 0),                "gray": (128, 128, 128)            }            if target_color_hex in color_map:                rgb = color_map[target_color_hex]            else:                rgb = (255, 255, 255)        else:            h = target_color_hex.lstrip('#')            rgb = tuple(int(h[i:i+2], 16) for i in (0, 2, 4))        r = int(rgb[0] * progress)        g = int(rgb[1] * progress)        b = int(rgb[2] * progress)        return f'#{r:02x}{g:02x}{b:02x}'    def update(self):        if self.game_over or self.game_won:            pass         else:            if self.is_charging:                if self.charge_power < self.MAX_CHARGE:                    self.charge_power += self.CHARGE_RATE            self.player['vy'] += self.GRAVITY            self.player['x'] += self.player['vx']            self.player['y'] += self.player['vy']            player_bottom = self.player['y'] + self.player['h']            player_left = self.player['x']            player_right = self.player['x'] + self.player['w']            for p in self.platforms:                plat_top = p['y']                plat_left = p['x']                plat_right = p['x'] + p['w']                if player_right > plat_left and player_left < plat_right:                    if player_bottom > plat_top:                        prev_bottom = player_bottom - self.player['vy']                        if self.player['vy'] > 0 and prev_bottom <= plat_top:                            self.player['y'] = plat_top - self.player['h']                            self.player['vy'] = 0                            self.player['vx'] = 0                            break                        else:                            self.game_over = True                            break            if self.player['x'] > 1200:                self.game_won = True            if self.player['y'] > 500:                self.game_over = True        current_state = 'won' if self.game_won else ('over' if self.game_over else 'playing')        if current_state != self.game_state:            self.game_state = current_state            self.text_fade = 0.0        if self.text_fade < 1.0:            self.text_fade += 0.03             if self.text_fade > 1.0:                self.text_fade = 1.0        self.draw()    def draw(self):        self.canvas.delete("all")        for p in self.platforms:            self.canvas.create_rectangle(                p['x'], p['y'],                 p['x'] + p['w'], p['y'] + p['h'],                 fill="#222222", outline=""            )        p = self.player        self.canvas.create_rectangle(            p['x'], p['y'],             p['x'] + p['w'], p['y'] + p['h'],             fill="white", outline=""        )        if self.is_charging:            ratio = self.charge_power / self.MAX_CHARGE             bar_width = ratio * 40             if ratio <= 0.5:                local_ratio = ratio * 2                r = 255                 g = int(255 * (1 - local_ratio))                b = 0            else:                local_ratio = (ratio - 0.5) * 2                r = int(255 - (255 - 139) * local_ratio)                g = 0                 b = 0             color_hex = f'#{r:02x}{g:02x}{b:02x}'            self.canvas.create_rectangle(                p['x'], p['y'] - 10,                p['x'] + bar_width, p['y'] - 5,                fill=color_hex, outline=""            )        if self.game_over:            text_color = self._get_faded_color("red", self.text_fade)            self.canvas.create_text(580, 200, text="万物皆生,唯你独枯。茫茫天地间,竟全然无你托身之所……", fill=text_color, font=("STKaiti", 30))            text_color = self._get_faded_color("grey", self.text_fade)            self.canvas.create_text(90, 30, text="R: retry,  T: exit", fill=text_color, font=("times", 12))        elif self.game_won:            text_color = self._get_faded_color("#00ff00", self.text_fade)            self.canvas.create_text(450, 200, text="穿尽千山与万水,始知天地本来宽.", fill=text_color, font=("STKaiti", 30))            text_color = self._get_faded_color("grey", self.text_fade)            self.canvas.create_text(90, 30, text="R: retry,  T: exit", fill=text_color, font=("times", 12))        else:            text_color = self._get_faded_color("white", self.text_fade)            self.canvas.create_text(450, 70, text="正入万山圈子里,一山放过一山拦——", fill=text_color, font=("STKaiti", 20))    def game_loop(self):        self.update()        self.top.after(20, self.game_loop)    def restart_game(self, event=None):        self.reset_game()    def close_game(self, event=None):        self.top.destroy()class OffWorkCountdownApp:    def __init__(self, root):        self.root = root         self.root.title("下班倒计时界面")        self.root.geometry("590x390")        self.root.configure(bg=BG_COLOR)        self.title_font = ("arial", 18, "bold")        self.label_font = ("arial", 12)        self.time_font  = ("arial", 22, "bold")        self.btn_font   = ("arials", 11)        self.create_widgets()        self.update_time()    def create_widgets(self):        main = tk.Frame(self.root, bg=BG_COLOR)        main.pack(fill="both", expand=True, padx=15, pady=10)        left = tk.Frame(main, bg=BG_COLOR)        left.pack(side="left", fill="both", expand=True, padx=(0, 20))        tk.Label(left, text="    ~下班倒计时~ ",                 font=self.title_font, bg=BG_COLOR, fg=TITLE_COLOR).pack(pady=(0, 20), anchor="w")        f1 = tk.Frame(left, bg=BG_COLOR)        f1.pack(pady=8, fill="x")        tk.Label(f1, text="离下班还有:", font=self.label_font,                 bg=BG_COLOR, fg=FG_COLOR).pack(anchor="w")        self.lbl_off_work = tk.Label(f1, text="计算中...", font=self.time_font,                                     bg=BG_COLOR, fg=ACCENT_RED)        self.lbl_off_work.pack(anchor="w", pady=(5, 0))        f2 = tk.Frame(left, bg=BG_COLOR)        f2.pack(pady=8, fill="x")        tk.Label(f2, text="离周末还有:", font=self.label_font,                 bg=BG_COLOR, fg=FG_COLOR).pack(anchor="w")        self.lbl_friday = tk.Label(f2, text="计算中...", font=self.time_font,                                   bg=BG_COLOR, fg=ACCENT_CYAN)        self.lbl_friday.pack(anchor="w", pady=(5, 0))        f3 = tk.Frame(left, bg=BG_COLOR)        f3.pack(pady=8, fill="x")        tk.Label(f3, text="离节假日还有:", font=self.label_font,                 bg=BG_COLOR, fg=FG_COLOR).pack(anchor="w")        self.lbl_holiday = tk.Label(f3, text="计算中...", font=("arial", 16),                                    bg=BG_COLOR, fg=ACCENT_YELLOW)        self.lbl_holiday.pack(anchor="w", pady=(5, 0))        RoundedButton(left, text="⚙️设置下班时间",                      command=self.open_settings).pack(pady=(30, 0), anchor="w")        right = tk.Frame(main, bg=BG_COLOR, width=390, height=390)        right.pack(side="right", fill="y")        right.pack_propagate(False)        mask = tk.Frame(right, bg=MASK_COLOR, width=360, height=370)        mask.place(relx=0.5, rely=0.5, anchor="center")        self.cat_img = None         if os.path.exists(CAT_IMAGE_PATH):            try:                self.cat_img = create_rounded_image(CAT_IMAGE_PATH, size=(320, 320), radius=10)                if self.cat_img:                    img_label = tk.Label(right, image=self.cat_img, bg=MASK_COLOR, bd=0, cursor="hand2")                    img_label.place(relx=0.5, rely=0.5, anchor="center")                    img_label.bind("<Button-1>", lambda e: self.open_game())                else:                    from PIL import Image, ImageTk                     img = Image.open(CAT_IMAGE_PATH)                    img = img.resize((320, 320), Image.LANCZOS)                    self.cat_img = ImageTk.PhotoImage(img)                    img_label = tk.Label(right, image=self.cat_img, bg=MASK_COLOR, bd=0, cursor="hand2")                    img_label.place(relx=0.5, rely=0.5, anchor="center")                    img_label.bind("<Button-1>", lambda e: self.open_game())            except ImportError:                tk.Label(right, text="(需安装Pillow才能显示图片哦)\npip install pillow",                         bg=MASK_COLOR, fg=FG_COLOR, font=("arial", 11),                         justify="center").place(relx=0.5, rely=0.5, anchor="center")        else:            tk.Label(right, text=f"这里本该有只哈基米。",                     bg=MASK_COLOR, fg=FG_COLOR, font=("arial", 10),                     justify="center").place(relx=0.5, rely=0.5, anchor="center")    def update_time(self):        global off_work_time_str         text, color = calculate_time_diff(off_work_time_str)        self.lbl_off_work.config(text=text, fg=color)        text, color = get_weekend_diff(off_work_time_str)        self.lbl_friday.config(text=text, fg=color)        days, name = get_next_holiday_info()        self.lbl_holiday.config(text=f"{days}天 ({name})")        self.root.after(1000, self.update_time)    def open_settings(self):        top = tk.Toplevel(self.root)        top.title("设置")        top.geometry("320x160")        top.configure(bg=POPUP_BG)        tk.Label(top, text="请输入下班时间 (HH:MM:SS):",                 bg=POPUP_BG, fg=FG_COLOR, font=("arial", 10)).pack(pady=15)        entry = tk.Entry(top, font=("arial", 12), justify="center",                         bg="#3c3f41", fg="white", insertbackground="white")        entry.insert(0, off_work_time_str)        entry.pack(pady=5)        entry.focus_set()        def save():            global off_work_time_str             new_time = entry.get()            try:                h, m, s = map(int, new_time.split(':'))                if 0 <= h < 24 and 0 <= m < 60 and 0 <= s < 60:                    off_work_time_str = new_time                     messagebox.showinfo("成功", "下班时间已更新!")                    top.destroy()                else:                    messagebox.showerror("错误", "时间数值不合法!")            except Exception:                messagebox.showerror("错误", "格式错误,请使用 HH:MM:SS")        tk.Button(top, text="确定", command=save,                  bg=BUTTON_COLOR, fg=BUTTON_TEXT, font=("arial", 10),                  relief="flat").pack(pady=15)    def open_game(self):        MiniGameApp(self.root)if __name__ == "__main__":    root = tk.Tk()    app = OffWorkCountdownApp(root)    root.mainloop()
该小程序以倒计时量化下班期待,以优美的诗词提供情绪情绪,为打工人提供了一个对抗职场倦怠的“精神按摩仪”。
-END-
往期:
零基础如何用Deepseek自制游戏【Python】
Chrome小恐龙C++硬核复现(上古年代无AI代码)
一文速通决策树和随机森林算法(Matlab实战算例)
PINN+CFD简版综述(物理信息神经网络应用于计算流体力学)
工程优化万能思路:神经网络代理模型&智能优化算法
浙江省温州市:改革开放实践与民营经济产业转型【综述长文】做梦做出一套算法?
五种机器学习模型(强行)解决实际问题+代码

最新文章

随机文章