首页 > 编程语言 >基于Python的桌面定时提醒小程序

基于Python的桌面定时提醒小程序

时间:2024-06-10 10:34:03浏览次数:30  
标签:桌面 Python text self grid tk time 定时 row

 分享一个自己之前做的小程序,主要功能有两个:

  1. 可以间隔固定时间弹窗提醒,间隔的时间以及重复的次数可以自己选定,提示的内容也可以手动输入;
  2. 设定具体的时间点,定时提醒,提示的内容也可以手动输入;

自己用了这个小程序已经快两年了,感觉体验还不错,所以就拿出来分享下,小程序是用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("<<ComboboxSelected>>", 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("<<ComboboxSelected>>", 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 < 0:
            messagebox.showinfo('警告', '请输入正确的时间')
            self.rmhour.set(current_time.hour)
            return False
        if min_test > 59 or hour_test < 0:
            messagebox.showinfo('警告', '请输入正确的时间')
            self.rmmin.set(current_time.minute)
            return False
        return True

    def stop_fun2(self):
        self.stop_flag_fun2 = True
        self.display_frame_fun2.config(text='请重新开始!')

    def progress_fun2(self):
        self.msg2 = self.text2.get('0.0', 'end')
        # 按下开始后锁定_rmhour和_rmmin参数
        if self.input_valid():
            self._rmhour = self.spin_hour.get()
            self._rmmin = self.spin_min.get()
            threading.Thread(target=self._progress_fun2, args=()).start()

    def _progress_fun2(self):
        self.stop_flag_fun2 = False
        self.start_button2.config(text='运行中', state='disable')
        try:
            minute_input = self._minute
            close_time = str(self._rmhour) + ':' + str(self._rmmin)
            close_time = datetime.datetime.strptime(close_time, '%H:%M')
            while True:
                if self.stop_flag_fun2:
                    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
                if gap_time.days < 0:
                    gap_time += datetime.timedelta(days=1)
                hours = int(str(gap_time).split(':')[-3])
                minutes = int(str(gap_time).split(':')[-2])
                seconds = int(str(gap_time).split(':')[-1])
                warn_msg = '距离定时提醒还有{}小时{}分钟{}秒'.format(hours, minutes, seconds,)
                if not hours and not minutes and not seconds:
                    self.display_frame_fun2.config(text=warn_msg)
                    break
                self.display_frame_fun2.config(text=warn_msg)
            if not self.stop_flag_fun2:
                messagebox.showinfo('提醒', self.msg2)
            # print("当前运行的线程数:%d" % len(threading.enumerate()))
        finally:
            self.stop_flag_fun2 = False
            self.display_frame_fun2.config(text='定时提醒功能待开始...')
            self.start_button2.config(text='开始', state='active')


if __name__ == '__main__':
    My_reminder = Reminder()
    My_reminder.root.mainloop()

如果要修改默认初始的值,也可以直接调整源程序,下次自己打开就不需要重新调整了。

标签:桌面,Python,text,self,grid,tk,time,定时,row
From: https://blog.csdn.net/Jayellow/article/details/139570113

相关文章

  • Python 机器学习基础:掌握 Pandas 数据处理库的奥秘
    在Python的机器学习领域中,Pandas是一个不可或缺的工具。它不仅提供了强大的数据结构,还拥有数据处理和分析的能力,是数据科学家和机器学习工程师的得力助手。本文将深入探讨Pandas的核心功能,并通过实际案例,展示其在机器学习项目中的关键作用。1.Pandas简介Pandas是......
  • python打印一颗桃花树
     以下是使用Python的turtle库来绘制一棵梅花树,并添加落叶效果的代码:importturtleimportrandom#设置画布和画笔canvas=turtle.Screen()canvas.bgcolor("black")pen=turtle.Turtle()pen.speed(0)pen.penup()pen.left(90)pen.backward(200)pen.pendown()#......
  • 大学生如何高效学习Python
     在数字化时代,编程技能已成为大学生必备的技能之一。Python,以其简洁的语法和强大的功能,成为了最受欢迎的编程语言之一。对于大学生来说,掌握Python不仅能够提升个人的竞争力,还能在学术和职业发展中发挥重要作用。1.明确学习目标首先,大学生应该明确自己学习Python的目的。是......
  • 基于粒子群优化算法的计及需求响应的风光储能微电网日前经济调度(Python代码实现)
    目录1概述2知识点及数学模型3 算例实现3.1算例介绍3.2风光参与的模型求解3.3风光和储能参与的模型求解3.5风光储能和需求响应都参与模型求解3.6结果分析对比 4Python代码及算例数据1概述近年来,微电网、清洁能源等已成为全球关注的热点。清洁能源在我国可......
  • 运筹学练习Python精解——网络计划技术
    练习1某新产品研制项目的各项工序、所需时间及相互关系如下表所示,试画出该项目的网络图,试求出关键路线。工序工序代号所需时间紧后工序产品及工艺设计A60B,C,D,E外购配套件B45K下料、锻件C10F工装制造1D20G,H木模、铸件E40H机械加......
  • python-10-数据处理得学:while+for循环搭配使用,排查数据和除重
    学习内容:《python编程:从入门到实践》第二版知识点:whilefor循环搭配使用,利用while排查数据,删除重复选项练习内容:练习7-8:熟食店创建一个名为sandwich_orders的列表,在其中包含各种三明治的名字,再创建一个名为finished_sandwiches的空列表。遍历列表sandwich_orders,对于其中......
  • python-7-求问,打印嵌套字典中的信息时,出现重复怎么解决?
    ​​​​​​学习内容:《python编程:从入门到实践》知识点:字典、键值对、嵌套#练习6-11:城市创建一个名为cities的字典,将三个城市名用作键。对于每座城市,都创建一个字典,并在其中包含该城市所属的国家、人口约数以及一个有关该城市的事实。在表示每座城市的字典中,应包含co......
  • python系列:FastAPI系列 10-路由管理APIRouter
    FastAPI系列10-路由管理APIRouterFastAPI系列10-路由管理APIRouter前言一、路由管理APIRouter二、FastAPI主体总结FastAPI系列10-路由管理APIRouter前言在fastapi中也有类似的功能通过APIRouter来管理一、路由管理APIRouter正在开发一个应用程序或We......
  • mac python 包管理工具 pip 的配置
     python3--versionPython3.12.3brewinstallpython@3.12pip3configsetglobal.index-urlhttps://pypi.tuna.tsinghua.edu.cn/simplepip3configsetglobal.break-system-packagestrue pip3installaiohttppython包管理工具pip的配置 近几年来,python的包......
  • python-数据分析-Pandas-2、DataFrame对象
    如果使用pandas做数据分析,那么DataFrame一定是被使用得最多的类型,它可以用来保存和处理异质的二维数据。这里所谓的“异质”是指DataFrame中每个列的数据类型不需要相同,这也是它区别于NumPy二维数组的地方。DataFrame提供了极为丰富的属性和方法,帮助我们实现对数据的重塑、......