基于Python的桌面定时提醒小程序
分享一个自己之前做的小程序,主要功能有两个:
- 可以间隔固定时间弹窗提醒,间隔的时间以及重复的次数可以自己选定,提示的内容也可以手动输入;
- 设定具体的时间点,定时提醒,提示的内容也可以手动输入;
自己用了这个小程序已经快两年了,感觉体验还不错,所以就拿出来分享下,小程序是用Python写的,当时也是自学Python一段时间了,结合网上找的一些类似的程序,按自己需求整合调整了一番,自己用下来觉得不错的点有几个:
- 程序很小,总共就12K,有python环境和几个必要的库就可以运行。运行时基本不占资源
- 实时显示倒计时,到时间后会弹出一个置顶的小窗口,很适合用来提醒久坐和喝水
- 下次循环提醒的开始要自己手动点掉置顶的弹窗才会开始,所以中间去忙其他事都没关系,回来需要让它开始时再点掉就可以了
- 两个提醒的功能不会相互冲突
下面介绍下背后的程序核心内容以及程序的界面
1.程序核心内容
这个python的小程序,核心的库就两个,一个是Threading模块,用来并行处理倒计时;另一个是Tkinter模块,创建GUI界面
1.1Threading模块
Threading模块,主要是为了实现多线程,可以实现倒计时里面的time.sleep()不占用过多资源,也可以让两个提醒功能不冲突,这个模块本身是python的内置库,所以也不需要额外安装。
这里主要就用了threading.Thread() 这个函数,用来启动倒计时程序,具体的内容我就不班门弄斧了,可以参考站内的讲解
threading 模块的 Thread 类的使用_threading.thread-CSDN博客
1.2Tkinter模块
Tkinter是为了创建一个GUI界面,需要设置一些输入,比如间隔时间、间隔次数、提示的内容以及开始停止这类按钮。涉及的Tk模块的小组件也不少,例如下拉框Combobox,按钮Button,文本Text,微调节器Spinbox等等。
整个GUI的界面布局用的是grid,然后就是把各个需要的组件放到合适的位置,并设定好内部传递的参数。
2.程序界面介绍
其实整个界面也比较简单,基本操作个一两次就知道了,基本就是设定下初始的参数还有需要提醒的内容,然后点击开始即可。随后对应功能下方的提示框就回开始显示倒计时。
3. 完整代码
# -*- coding:utf-8 -*- """ Reminder 小工具 功能1: 间隔一定时间提醒,可设定间隔时间、循环次数、提醒消息 功能2: 设定具体时间,提醒对应时间的内容 """ import time import datetime import threading import tkinter as tk from tkinter import messagebox from tkinter import ttk class Reminder(object): def __init__(self): self.root = tk.Tk() self.root.title('Reminder 小工具') self.root.wm_attributes("-topmost", True) # GUI置顶,置顶后可手动最小化 self.build_select_button_fun1() # 功能1的操作区 self.build_display_fun1() # 功能1的显示区 self.stop_flag_fun1 = False self.build_select_button_fun2() # 功能2的操作区 self.build_display_fun2() # 功能2的显示区 self.stop_flag_fun2 = False # 功能1对应的参数 self.msg1 = '' self.freq_count = 0 self.minute = 30 self._minute = 30 self.freq = 10 self._freq = 10 # 功能2对应的参数 self.msg2 = '' current_time = datetime.datetime.now() self._rmhour = current_time.hour self._rmmin = current_time.minute self.set_window_center(window=self.root, width=660, height=340) def build_display_fun1(self): frame = tk.Frame(relief='ridge', borderwidth=5) self.label = tk.Label(frame, text='间隔提醒功能待开始.....', font=('楷体', 15, 'bold'), fg='#87cefa') self.label.grid(row=0, column=0, sticky=tk.EW, padx=70) frame.grid(row=1, column=0, sticky=tk.NSEW) def build_select_button_fun1(self): frame1 = tk.Frame(relief='groove', borderwidth=5) tk.Label(frame1, text='功能1:循环间隔提醒 ').grid(row=0, column=0, sticky=tk.W) tk.Label(frame1, text='选择间隔时间').grid(row=1, column=0, sticky=tk.W) self.cv1 = tk.StringVar() self.com1 = ttk.Combobox(frame1, textvariable=self.cv1) self.com1.grid(row=1, column=1) self.com1['value'] = ("10分钟", "15分钟", "20分钟", "30分钟", "45分钟", "60分钟") self.com1.current(3) # 绑定combobox self.com1.bind("", self.get_time) tk.Label(frame1, text='选择循环次数').grid(row=1, column=2, sticky=tk.W, padx=15) self.cv2 = tk.StringVar() self.com2 = ttk.Combobox(frame1, textvariable=self.cv2) self.com2.grid(row=1, column=3) self.com2['value'] = ("1次", "2次", "3次", "4次", "5次", "8次", "10次", "15次", "20次", "25次", "30次") self.com2.current(9) # 绑定combobox self.com2.bind("", self.get_freq) tk.Label(frame1, text='输入需提醒的内容').grid(row=2, column=0, sticky=tk.W) self.start_button = tk.Button(frame1, text='开始', command=self.progress_fun1, bg='LightSkyBlue') self.start_button.grid(row=1, column=4, sticky=tk.W, padx=15) tk.Button(frame1, text='停止', command=self.stop_fun1, bg='tomato').grid(row=2, column=4, sticky=tk.W, padx=15) self.text1 = tk.Text(frame1, height=4, width=62) self.text1.insert("insert", "已连续坐30分钟!\n起来喝水!") self.text1.grid(row=2, column=1, columnspan=3) frame1.grid(row=0, column=0, sticky=tk.NSEW) def build_display_fun2(self): frame3 = tk.Frame(relief='ridge', borderwidth=5) self.display_frame_fun2 = tk.Label(frame3, text='定时提醒功能待开始...', font=('楷体', 15, 'bold'), fg='#fc5531') self.display_frame_fun2.grid(row=0, column=0, sticky=tk.EW, padx=70) frame3.grid(row=3, column=0, sticky=tk.NSEW) def build_select_button_fun2(self): frame4 = tk.Frame(relief='groove', borderwidth=5) tk.Label(frame4, text='功能2:定时提醒 ').grid(row=0, column=0, sticky=tk.W) tk.Label(frame4, text='选择提醒时间').grid(row=1, column=0, sticky=tk.W) self.rmhour = tk.IntVar() self.spin_hour = tk.Spinbox(frame4, from_=0, to=23, textvariable=self.rmhour, validate='key') self.spin_hour.grid(row=1, column=1) tk.Label(frame4, text='时').grid(row=1, column=2, sticky=tk.W) self.rmmin = tk.IntVar() self.spin_min = tk.Spinbox(frame4, from_=0, to=59, textvariable=self.rmmin, validate='key') self.spin_min.grid(row=1, column=3) tk.Label(frame4, text='分').grid(row=1, column=4, sticky=tk.W) current_time = datetime.datetime.now() self.rmhour.set(current_time.hour) self.rmmin.set(current_time.minute) tk.Label(frame4, text='输入需提醒的内容').grid(row=2, column=0, sticky=tk.W) self.start_button2 = tk.Button(frame4, text='开始', command=self.progress_fun2, bg='LightSkyBlue') self.start_button2.grid(row=1, column=5, sticky=tk.W, padx=15) tk.Button(frame4, text='停止', command=self.stop_fun2, bg='tomato').grid(row=2, column=5, sticky=tk.W, padx=15) self.text2 = tk.Text(frame4, height=4, width=52) self.text2.grid(row=2, column=1, columnspan=3) frame4.grid(row=2, column=0, sticky=tk.NSEW) def quit(self): self.root.destroy() self.root.quit() @staticmethod def set_window_center(window, width=300, height=300): ws = window.winfo_screenwidth() hs = window.winfo_screenheight() x = (ws / 2) - (width / 2) y = (hs / 2) - (height / 2) window.geometry('%dx%d+%d+%d' % (width, height, x, y)) def get_time(self, event): # 下拉框选取时间时,即获取minute参数 self.minute = int(self.com1.get()[:-2]) # print(self.minute) def get_freq(self, event): # 下拉框选取次数时,即获取freq参数 self.freq = int(self.com2.get()[:-1]) # print(self.freq) def stop_fun1(self): self.stop_flag_fun1 = True self.label.config(text='请重新开始!') def progress_fun1(self): self.msg1 = self.text1.get('0.0', 'end') # 按下开始后锁定_minute和_freq参数 self._minute = self.minute self._freq = self.freq self.freq_count = 0 threading.Thread(target=self._progress_fun1, args=()).start() def _progress_fun1(self): self.stop_flag_fun1 = False self.start_button.config(text='运行中', state='disable') try: minute_input = self._minute close_time = (datetime.datetime.now() + datetime.timedelta(minutes=minute_input)).strftime('%H:%M:%S') close_time = datetime.datetime.strptime(close_time, '%H:%M:%S') while True: if self.stop_flag_fun1: break time.sleep(1) current_time = datetime.datetime.strptime(datetime.datetime.now().strftime('%H:%M:%S'), '%H:%M:%S') gap_time = close_time - current_time hours = int(str(gap_time).split(':')[-3]) minutes = int(str(gap_time).split(':')[-2]) seconds = int(str(gap_time).split(':')[-1]) warn_msg = '距离下次提醒还有{}分钟{}秒; 已提醒{}次(共{}次)'.format(minutes, seconds, self.freq_count, self._freq) if not hours and not minutes and not seconds: self.label.config(text=warn_msg) break self.label.config(text=warn_msg) if not self.stop_flag_fun1: messagebox.showinfo('提醒', self.msg1) # print("当前运行的线程数:%d" % len(threading.enumerate())) finally: if not self.stop_flag_fun1 and not self.freq_count == self._freq - 1: self.freq_count += 1 threading.Thread(target=self._progress_fun1, args=()).start() else: messagebox.showinfo('提醒', '循环间隔提醒已结束,感谢使用!') self.stop_flag_fun1 = False self.label.config(text='间隔提醒功能待开始.....') self.start_button.config(text='开始', state='active') def input_valid(self): current_time = datetime.datetime.now() try: hour_test = int(self.spin_hour.get()) min_test = int(self.spin_min.get()) except: messagebox.showinfo('警告', '请输入正确的时间') self.rmhour.set(current_time.hour) self.rmmin.set(current_time.minute) return False if hour_test > 23 or hour_test 59 or hour_test
如果要修改默认初始的值,也可以直接调整源程序,下次自己打开就不需要重新调整了。