桌面美化 Python tkinter倒计时工具

桌面美化 Python tkinter倒计时工具

  • 效果
  • 一、壁纸设计
  • 二、倒计时小工具实现
    • 1.引入库
    • 2.倒计时函数
    • 3.绘制UI
      • 载入数据以及创建窗口
      • 创建Label控件
      • 控件布局
      • 绘制分割线
      • 绘制子窗口,用于修改倒计时目标
      • 其它设置
  • 完整代码
  • 打包并开机自启动
    • 打包成EXE
    • 开机自启动


效果

使用tkiner编写倒计时工具并放在桌面上,配合ps制作的壁纸,实现桌面美化
效果如下:

桌面美化 Python tkinter倒计时工具_第1张图片


一、壁纸设计

根据桌面文件布局风格、个人喜好、可以自行搜集或设计

我这里是用 PS 制作的壁纸,这里需要配合桌面的布局风格来制作,我主要就是按照布局绘制了底色,然后发现上边有点空,加了句话,这里使用的壁纸如下:桌面美化 Python tkinter倒计时工具_第2张图片


二、倒计时小工具实现

设计啥的咱也不是专业的咱也不懂也不好说,直接说软件咋做的吧
初心就是tkinter的试水,之前用pyqt5做过一些东西,但是打包后70多Mb,这次想试试tkiner
(tkinter是真的轻便,也是真的不个性)

废话不多说,开撸!

1.引入库

因为需要不断刷新我们的倒计时,而tkinter的线程又是阻塞的,所以这里使用多线程

import tkinter as tk
from threading import Thread
import time

2.倒计时函数

主要就是根据时间截之差,计算相差的天数、以及余下的小时数、分钟数:

def get_time(handle):
    while True:
        s = handle.endtime - int(time.time())
        days = int(s / 86400)
        hours = int((s % 86400) / 3600)
        mins = int((s % 3600) / 60)
        handle.LabelDays.config(text=f'{days} 天')
        handle.LabelHours.config(text=f'{hours} 时')
        handle.LabelMins.config(text=f'{mins} 分')
        handle.LabelS.config(text=f'共计 {format(s,",")} 秒')
        time.sleep(1)

handle 是后边绘制UI时创建的类在调用此函数时传入的self(可以理解为继承???)
int() 用于取整(直接舍弃小数部分)
% 用于取余数
config 用于修改控件

3.绘制UI

载入数据以及创建窗口

首先,创建类,载入我们的倒计时数据,然后创建我们的窗口
class APP():
    def __init__(self):
        with open('config','r',encoding='utf8') as f:
            self.Target = f.readline().strip()
            self.endtime=eval(f.readline().strip())
        self.window = tk.Tk()
        # 设置窗口大小以及位置
        self.window.geometry('405x270+1128+290')

这里的 config 文件,是我存放倒计时目标以及时间截的地方
config内容:

开学
1613577600

self.window.geometry(‘405x270+1128+290’) 是指窗口宽为405,高为270,距离屏幕左边为1128,距离屏幕上边为290
这里数值的大小是我自己尝试出来的


创建Label控件

    def set_text(self):
        self.LabelTitle = tk.Label(self.window, text=f'距离 {self.Target} 还有', bg='#f9aea8',fg='white', font=('方正青铜体简体', 17))
        self.LabelDays = tk.Label(self.window, text='00 天', bg='#f9aea8', fg='white', font=('方正青铜体简体', 17))
        self.LabelHours = tk.Label(self.window, text='00 时', bg='#f9aea8', fg='white', font=('方正青铜体简体', 17))
        self.LabelMins = tk.Label(self.window, text='00 分', bg='#f9aea8', fg='white', font=('方正青铜体简体', 17))
        self.LabelS = tk.Label(self.window, text='共计 000,000 秒', bg='#f9aea8', fg='white', font=('方正青铜体简体', 17))

这里用到的字体为 方正青铜体简体 ,可以改为自己电脑上的自己喜欢的字体。
非常烦的一件事就是tkinter的控件带背景颜色且不能透明,这也是为何我最终选择了纯色背景——方便

如果想用图片做背景,还想控件背景透明的话,可以参考 这篇文章,作者通过切割窗口背景图片然后将切割后的图片作为控件背景的方法,另辟蹊径的解决了这个问题,Nice!


控件布局

    def set_layout(self):
        tk.Label(self.window, bg='#f9aea8').pack(expand='yes')  # 仅用来占地方,避免其它控件位置过于靠上
        self.LabelTitle.pack(expand='yes')
        self.LabelDays.pack(expand='yes')
        self.LabelHours.pack(expand='yes')
        self.LabelMins.pack(expand='yes')
        self.LabelS.pack(expand='yes')
        tk.Label(self.window, bg='#f9aea8').pack()  # 仅用来占地方,避免其它控件位置过于靠下

这里采用的pack的方法来布局的,关于pack,可以参考这里。

绘制分割线

这里还画了两条白色的分割线用于美化

    def set_Line(self):
        self.CanvasBg = tk.Canvas(self.window, bg='#f9aea8', width=405, height=270)
        self.CanvasBg.place(x=0, y=0)
        self.CanvasBg.create_line(0, 73, 405, 73, fill='white')
        self.CanvasBg.create_line(0, 200, 405, 200, fill='white')

self.CanvasBg.create_line(0, 73, 405, 73, fill=‘white’)
是指画一条从(0,73)到(405,73)的白色线段

注意:需要在Canvas控件上进行绘制。

绘制子窗口,用于修改倒计时目标

    def updata_window(self,event):  # 绘制子窗口
        self.UpdataWindow = tk.Toplevel()
        self.UpdataWindow['bg'] = '#f6ccb4'
        self.UpdataWindow.title('修  改')
        self.UpdataWindow.geometry('240x140')

        self.EntryTarget = tk.Entry(self.UpdataWindow)  # 目标输入框
        self.EntryEndtime = tk.Entry(self.UpdataWindow)  # 时间截输入框

        tk.Label(self.UpdataWindow,bg='#f6ccb4', text='目  标').grid(row=1, column=1,pady=10,padx=5)
        self.EntryTarget.grid(row=1,column=2)
        tk.Label(self.UpdataWindow,bg='#f6ccb4', text='时间截').grid(row=2,column=1,pady=10,padx=5)
        self.EntryEndtime.grid(row=2,column=2)
        # 修改按钮
        tk.Button(self.UpdataWindow, bg='#f9aea8', fg='white',width='19', text='修改',command=self.updata).grid(row=3,column=2)

    def updata(self):  # 用于将修改更新到父窗口
        if self.EntryEndtime.get():
            self.Target = self.EntryTarget.get()
            self.endtime = eval(self.EntryEndtime.get())  # 获取时间截数值
            self.LabelTitle.config(text=f'距离 {self.Target} 还有')
            self.UpdataWindow.destroy()  # 销毁子窗口

这里采用的是的是grid的布局方式,简单来说,按照表格的方式布局,roe是第几行,column是第几列,还有其它参数这里没用到,如:
padx 是单元格左右间距
pady 是单元格上下间距
ipadx是单元格内部元素与单元格左右的间距
ipady是单元格内部元素与单元格上下的间距

其它设置

    def set_others(self):
        self.window.resizable(0, 0)  # 固定窗口大小,不可调整
        self.window.overrideredirect(True)  # 去除窗口标题栏
        self.LabelTitle.bind("", self.updata_window)  # 绑定鼠标左击事件,用于修改目标
        Thread(target=get_time,args=(self,)).start()  # 多线程启动刷新时间函数

最后,在init里该调用调用,在外面该初始化初始化,完整代码如下

完整代码

import tkinter as tk
from threading import Thread
import time


def get_time(handle):
    while True:
        s = handle.endtime - int(time.time())
        days = int(s / 86400)
        hours = int((s % 86400) / 3600)
        mins = int((s % 3600) / 60)
        handle.LabelDays.config(text=f'{days} 天')
        handle.LabelHours.config(text=f'{hours} 时')
        handle.LabelMins.config(text=f'{mins} 分')
        handle.LabelS.config(text=f'共计 {format(s,",")} 秒')
        time.sleep(1)


class APP():
    def __init__(self):
        with open('config','r',encoding='utf8') as f:
            self.Target = f.readline().strip()
            self.endtime=eval(f.readline().strip())
        self.window = tk.Tk()
        self.window.geometry('405x270+1128+290')
        self.set_Line()
        self.set_text()
        self.set_layout()
        self.set_others()

    def set_Line(self):
        self.CanvasBg = tk.Canvas(self.window, bg='#f9aea8', width=405, height=270)
        self.CanvasBg.place(x=0, y=0)
        self.CanvasBg.create_line(0, 73, 405, 73, fill='white')
        self.CanvasBg.create_line(0, 200, 405, 200, fill='white')

    def set_text(self):
        self.LabelTitle = tk.Label(self.window, text=f'距离 {self.Target} 还有', bg='#f9aea8',fg='white', font=('方正青铜体简体', 17))
        self.LabelDays = tk.Label(self.window, text='00 天', bg='#f9aea8', fg='white', font=('方正青铜体简体', 17))
        self.LabelHours = tk.Label(self.window, text='00 时', bg='#f9aea8', fg='white', font=('方正青铜体简体', 17))
        self.LabelMins = tk.Label(self.window, text='00 分', bg='#f9aea8', fg='white', font=('方正青铜体简体', 17))
        self.LabelS = tk.Label(self.window, text='共计 000,000 秒', bg='#f9aea8', fg='white', font=('方正青铜体简体', 17))

    def set_layout(self):
        tk.Label(self.window, bg='#f9aea8').pack(expand='yes')
        self.LabelTitle.pack(expand='yes')
        self.LabelDays.pack(expand='yes')
        self.LabelHours.pack(expand='yes')
        self.LabelMins.pack(expand='yes')
        self.LabelS.pack(expand='yes')
        tk.Label(self.window, bg='#f9aea8').pack()

    def set_others(self):
        self.window.resizable(0, 0)
        self.window.overrideredirect(True)
        self.LabelTitle.bind("", self.updata_window)
        Thread(target=get_time,args=(self,)).start()

    def updata_window(self,event):
        self.UpdataWindow = tk.Toplevel()
        self.UpdataWindow['bg'] = '#f6ccb4'
        self.UpdataWindow.title('修  改')
        self.UpdataWindow.geometry('240x140')

        self.EntryTarget = tk.Entry(self.UpdataWindow)
        self.EntryEndtime = tk.Entry(self.UpdataWindow)

        tk.Label(self.UpdataWindow,bg='#f6ccb4', text='目  标').grid(row=1, column=1,pady=10,padx=5)
        self.EntryTarget.grid(row=1,column=2)
        tk.Label(self.UpdataWindow,bg='#f6ccb4', text='时间截').grid(row=2,column=1,pady=10,padx=5)
        self.EntryEndtime.grid(row=2,column=2)
        tk.Button(self.UpdataWindow, bg='#f9aea8', fg='white',width='19', text='修改',command=self.updata).grid(row=3,column=2)

    def updata(self):
        if self.EntryEndtime.get():
            self.Target = self.EntryTarget.get()
            self.endtime = eval(self.EntryEndtime.get())
            self.LabelTitle.config(text=f'距离 {self.Target} 还有')
            self.UpdataWindow.destroy()


if __name__ == '__main__':
    myapp = APP()
    myapp.window.mainloop()

打包并开机自启动

打包成EXE

pyinstaller -D de_desktop.py -p venv\Lib\site-packages --noconsole

这里的 -D de_desktop.py 是指文件名是 de_desktop.py
-p venv\Lib\site-packages 是指库函数的目录在这里(我这里用的是相对路径)
–noconsole 是指不需要命令窗口(默认不加这句的话,启动程序后会有一个cmd似的窗口)

开机自启动

直接将打包好的EXE的快捷方式复制到开机启动项的文件夹内

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp

注意:win+d快捷键返回桌面时,程序界面会被隐藏,按alt+f4可以调出;其他方式返回桌面时没问题。
如果你有隐藏标题栏又同时不隐藏状态栏的方法,欢迎告知,在线求。

你可能感兴趣的:(创作生涯,python,gui,tkinter)