如何利用python制作一个自动休眠Win的工具

近日,公司供电不稳定,时不时断电,对台式机很不友好。在经历了两次早晨一来发现电脑前一晚被强行断电关机的不愉快后,我决定写一个晚上可以自动把电脑休眠的工具。

最终成品图如下:
焦点获取状态

下面是施工过程:

一、任务目标与分析

任务目标:

  • 每晚8点自动运行
  • 执行休眠动作前倒计时提醒
  • 可以取消休眠,可以把倒计时加时,可以重置倒计时时间
  • 倒计时以界面的方式出现(而不是命令行),且置顶+不可关闭,窗体可拖动

分析

二、界面设计/功能设计

1、界面大小与常见的右下角悬浮窗类似。
2、界面有三个按钮对应三个小功能,分别是“重置“、”加时“、”取消“。
3、为了不影响正常工作,界面应置顶且有一定的透明度,界面不在焦点时应把透明度进一步调低。界面应可拖动。
4、为了美观,应把python运行的命令行隐藏,将状态栏和标题栏隐藏。

三、代码实现

代码主要分为两个部分:窗体模块和计时模块

1、窗体模块:

(1) 隐藏命令行显示:
# 隐藏命令行窗口
import ctypes
#调用kernel32.dll获取当前命令行的句柄
whnd = ctypes.windll.kernel32.GetConsoleWindow()
if whnd != 0:
    #隐藏命令行窗口
    ctypes.windll.user32.ShowWindow(whnd, 0)
    #释放句柄资源(句柄类似于指针,这里只关闭了句柄,并不关闭线程)
    ctypes.windll.kernel32.CloseHandle(whnd)
(2) 界面

界面使用tkinter组件
依赖的包:

import tkinter
from tkinter import *

获取焦点、获取鼠标动作等事件需要将窗体绑定windows事件。窗体的绑定事件代码格式为:
root.bind("<B1-Motion>", change)

设定窗体的各项参数:

#创建根窗体
root = tkinter.Tk()

#初始化窗体
def tkinterInit():
    # 设定位置
    root.geometry('260x120-10-40')
    # UI窗口置于顶层
    root.wm_attributes('-topmost', 1)
    #标题栏标题
    root.title("即将休眠")
    # 背景色
    root["background"] = "white"
    # 设置透明度
    root.attributes("-alpha", 0.8)
    # 绑定win鼠标移动事件
    # <B1-Motion> 拖动左键触发事件
    # <B2-Motion> 拖动中键触发事件
    # <B3-Motion> 拖动右键触发事件
    root.bind("<B1-Motion>", change)
    # 鼠标左键按下,2表示中键,3表示右键;
    root.bind("<Button-1>", btnDown)
    # 获取焦点
    root.bind("<FocusIn>", focusIn)
    # 失去焦点
    root.bind("<FocusOut>", focusOut)

    # 不可改变窗口大小
    root.resizable(False, False)
    # 设置窗口为工具样式:
    # root.attributes("-toolwindow", True)
    # # 设置全屏:
    # root.attributes("-fullscreen", True)
    # 设置成脱离工具栏样式(取消标题栏和状态栏图标)
    root.overrideredirect(True)

创建窗口上的其他组件:

#创建窗口
def startTkinter():
    global timer
    tkinterInit()
    # 提示标签
    title = Label(root, text='距离休眠时间还有:', bg="white")
    # 时间显示标签
    timer = Label(root, textvariable=nowTime, fg="red", bg="white", font="黑体")
    #1000ms后调用updateTime函数
    timer.after(1000, updateTime)

    # “重置”与“加时”按钮需要在一行,故把两个按钮放入一个框架内。
    frame = tkinter.Frame(root)
    #按钮方法需要使用函数名(不带括号)或lambda表达式调用函数
    resetBtn = Button(frame, text='重置'
                      , command=resetTime
                      , width=12
                      , bg="white"
                      , relief='ridge'
                      )
    addBtn = Button(frame, text='加时5分钟'
                    , command=addTime
                    , width=12
                    , bg="white"
                    , relief='ridge'
                    )
    #放置重置按钮
    resetBtn.pack(side=LEFT)
    # 放置加时按钮
    addBtn.pack(side=RIGHT)


    quitBtn = Button(root, text='取消'
                     , command=lambda: root.quit()
                     , width=25
                     , bg="white"
                     , fg="Blue"
                     , relief='ridge'
                     )

    #放置提示文本标签
    title.pack()
    # 时间显示框的位置
    timer.place(x=150, y=20, anchor="center")
    #放置时间显示标签
    timer.pack()
    #放置“重置”与“加时”框架
    frame.pack()
    #放置取消按钮
    quitBtn.pack()

    #开启窗口
    root.mainloop()

鼠标拖动:
由于隐藏了标题栏,故无法直接拖动 。此时需要实现拖动界面来实现拖动动作。具体实现思路为:监听鼠标左键按下的动作,记录下当前鼠标在窗体中的位置,再监听鼠标滑动动作,计算鼠标相对上次的位移,获取窗体当前在win中的位置,最后鼠标在窗体上移动多少,窗体就在win上移动多少。以此实现鼠标直接拖动窗体的移动。

tkinterInit() 中已经绑定了鼠标事件:
# 绑定win鼠标移动事件
root.bind("<B1-Motion>", change)
# 鼠标左键按下,2表示中键,3表示右键;
root.bind("<Button-1>", btnDown)
以下为事件的具体实现:

oldX = 0
oldy = 0

# 鼠标移动窗体(具体原理就是鼠标在窗体上移动多少,窗体就在win上移动多少)
def change(event):
    global oldX, oldy
    # 获取窗体位置
    winX = root.winfo_x()
    winY = root.winfo_y()
    # 获取鼠标相对旧位置移动的位置
    x = event.x - oldX
    y = event.y - oldy
    root.geometry('260x120+' + str(winX + x) + '+' + str(winY + y))


# 监听鼠标按下事件
def btnDown(event):
    global oldX, oldy
    oldX = event.x
    oldy = event.y

当程序在焦点时(活动窗口)透明度设置为80%,不在焦点时透明度设置为45%。

# 获取焦点,设置透明度为0.8
def focusIn(event):
    root.attributes("-alpha", 0.8)

# 失去焦点设置透明度为0.45
def focusOut(event):
    root.attributes("-alpha", 0.45)

2、定时模块

下面是两个按钮和一个倒计时标签对应的函数:

# 重置时间
def resetTime():
    global timeNum, timer
    timeNum = defTimeNum
    nowTime.set(getNowTimeString(mode='str'))
#增加时间
def addTime():
    global timeNum
    timeNum = timeNum + 300
    nowTime.set(getNowTimeString(mode='str'))

时间显示label的定时调用函数:
startTkinter() 中已经将时间label绑定了该函数
timer.after(1000, updateTime)

# labal定时执行的任务
def updateTime():
    global timer
    nowTime.set(getNowTimeString())
    #循环调用达到计时的目的
    timer.after(1000, updateTime)

时间递减与逻辑判断函数:

def getNowTimeString(mode='general'):
    global timeNum
    if (timeNum > 0):
        if mode == 'general':
            timeNum = timeNum - 1
        minute = timeNum // 60
        seconds = timeNum % 60
        res = '{}分{}秒'.format((str(minute if minute >= 0 else 0)).zfill(2),
                              (str(seconds if seconds >= 0 else 0)).zfill(2))
        return res
    else:
        command()

最后定义命令函数即可:

# 到时间执行任务
def command():
    os.system('shutdown -h')
    root.quit()

最后,完整的代码如下:

import tkinter
from tkinter import *
from tkinter import messagebox

# 隐藏命令行窗口
import ctypes
#获取当前命令行的句柄
whnd = ctypes.windll.kernel32.GetConsoleWindow()
if whnd != 0:
    #隐藏命令行窗口
    ctypes.windll.user32.ShowWindow(whnd, 0)
    #释放句柄资源(句柄类似于指针,这里只关闭了句柄,并不关闭线程)
    ctypes.windll.kernel32.CloseHandle(whnd)

#创建根窗体
root = tkinter.Tk()

defTimeNum = 300
timeNum = defTimeNum

def getNowTimeString(mode='general'):
    global timeNum
    if (timeNum > 0):
        if mode == 'general':
            timeNum = timeNum - 1
        minute = timeNum // 60
        seconds = timeNum % 60
        res = '{}分{}秒'.format((str(minute if minute >= 0 else 0)).zfill(2),
                              (str(seconds if seconds >= 0 else 0)).zfill(2))
        return res
    else:
        command()


nowTime = StringVar()
nowTime.set(getNowTimeString())



def tkinterInit():
    # 设定位置
    root.geometry('260x120-10-40')
    # 置于顶层
    root.wm_attributes('-topmost', 1)
    root.title("即将休眠")
    # 透明度
    root["background"] = "white"
    # 设置透明度
    root.attributes("-alpha", 0.8)
    # 绑定win鼠标移动事件
    # <B1-Motion> 拖动左键触发事件
    # <B2-Motion> 拖动中键触发事件
    # <B3-Motion> 拖动右键触发事件
    root.bind("<B1-Motion>", change)
    # 鼠标左键按下,2表示中键,3表示右键;
    root.bind("<Button-1>", btnDown)
    # 获取焦点
    root.bind("<FocusIn>", focusIn)
    # 失去焦点
    root.bind("<FocusOut>", focusOut)

    # 不可改变窗口大小
    root.resizable(False, False)
    # 设置窗口为工具样式:
    # root.attributes("-toolwindow", True)
    # # 设置全屏:
    # root.attributes("-fullscreen", True)
    # 设置成脱离工具栏
    root.overrideredirect(True)

#创建窗口
def startTkinter():
    global timer
    tkinterInit()
    # 提示标签
    title = Label(root, text='距离休眠时间还有:', bg="white")
    # 时间显示标签
    timer = Label(root, textvariable=nowTime, fg="red", bg="white", font="黑体")
    #1000ms后调用updateTime函数
    timer.after(1000, updateTime)

    # “重置”与“加时”按钮需要在一行,故把两个按钮放入一个框架内。
    frame = tkinter.Frame(root)
    resetBtn = Button(frame, text='重置'
                      , command=resetTime
                      , width=12
                      , bg="white"
                      , relief='ridge'
                      )
    addBtn = Button(frame, text='加时5分钟'
                    , command=addTime
                    , width=12
                    , bg="white"
                    , relief='ridge'
                    )
    #放置重置按钮
    resetBtn.pack(side=LEFT)
    # 放置加时按钮
    addBtn.pack(side=RIGHT)


    quitBtn = Button(root, text='取消'
                     , command=lambda: root.quit()
                     , width=25
                     , bg="white"
                     , fg="Blue"
                     , relief='ridge'
                     )

    #放置提示文本标签
    title.pack()
    # 时间显示框的位置
    timer.place(x=150, y=20, anchor="center")
    #放置时间显示标签
    timer.pack()
    #放置“重置”与“加时”框架
    frame.pack()
    #放置取消按钮
    quitBtn.pack()

    #开启窗口
    root.mainloop()


# 到时间执行任务
def command():
    os.system('shutdown -h')
    root.quit()


# 重置时间
def resetTime():
    global timeNum, timer
    timeNum = defTimeNum
    nowTime.set(getNowTimeString(mode='str'))


def addTime():
    global timeNum
    timeNum = timeNum + 300
    nowTime.set(getNowTimeString(mode='str'))


def updateTime():
    global timer
    nowTime.set(getNowTimeString())
    timer.after(1000, updateTime)


oldX = 0
oldy = 0

# 鼠标移动窗体(具体原理就是鼠标在窗体上移动多少,窗体就在win上移动多少)
def change(event):
    global oldX, oldy
    # 获取窗体位置
    winX = root.winfo_x()
    winY = root.winfo_y()
    # 获取鼠标相对旧位置移动的位置
    x = event.x - oldX
    y = event.y - oldy
    root.geometry('260x120+' + str(winX + x) + '+' + str(winY + y))


# 监听鼠标按下事件
def btnDown(event):
    global oldX, oldy
    oldX = event.x
    oldy = event.y


# 获取焦点,设置透明度为0.8
def focusIn(event):
    root.attributes("-alpha", 0.8)


# 失去焦点设置透明度为0.45
def focusOut(event):
    root.attributes("-alpha", 0.45)


if __name__ == '__main__':
    startTkinter()

四、部署

打开任务计划程序:
任务计划程序
新建计划任务
在这里插入图片描述
名称自行设定、触发条件设定为每天20点、操作的设置如下:
在这里插入图片描述
“程序或脚本”为python的路径,如:D:\ProgramFiles\Anaconda3\python.exe
“添加参数”为上述代码文件的路径 如:D:\OA\自动休眠UI.py
“起始于”为python程序的上一级路径,如:D:\ProgramFiles\Anaconda3

如此,即可每晚8点打开该程序了。

五、成品

有焦点(透明度80%)
在这里插入图片描述
脱离焦点(透明度45%)
在这里插入图片描述
加时
在这里插入图片描述
取消(退出)
在这里插入图片描述
呐,已经退出了~

最终展示:
在这里插入图片描述

六、扩展:

这样的方法也可以制作成为桌面助手啦、网络悬浮窗啦等小功能组件。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 您好,为您编写一个文件自动分类工具代码: ``` import os import shutil def classify_files(src_dir, dst_dir): file_types = {} for filename in os.listdir(src_dir): file_path = os.path.join(src_dir, filename) if os.path.isfile(file_path): file_type = filename.split('.')[-1] if file_type not in file_types: os.makedirs(os.path.join(dst_dir, file_type)) file_types[file_type] = os.path.join(dst_dir, file_type) shutil.move(file_path, os.path.join(file_types[file_type], filename)) src_dir = '/path/to/src' dst_dir = '/path/to/dst' classify_files(src_dir, dst_dir) ``` 该代码会读取`src_dir`目录下的所有文件,并根据文件后缀分类到`dst_dir`目录下。比如,如果有一个名为`example.txt`的文本文件,它会被移动到`dst_dir/txt/`目录下。 希望对您有所帮助! ### 回答2: Python是一种高级编程语言,非常适合用于编写自动工具。下面是一个Python编写的文件自动分类工具的示例: 该工具的目标是为指定的文件夹中的文件进行自动分类。用户只需要提供要分类的文件夹路径和分类规则,工具就能自动将文件按照规则进行分类。 首先,用户需要在源代码中定义分类规则。例如,用户可以使用文件的扩展名作为分类依据,将具有相同扩展名的文件放入同一个文件夹。用户可以通过修改代码中的分类规则来满足个性化的需求。 接下来,工具会遍历指定文件夹中的所有文件。使用Python的os库可以轻松地获取文件夹中的文件列表。然后,工具会根据分类规则将文件移动到相应的文件夹中。使用Python的shutil库可以方便地实现文件的移动操作。 工具还可以对每个文件夹进行计数,以便用户了解每个分类中有多少个文件。可以使用Python的os库来获取文件夹内文件的数量。 最后,工具会生成一个报告,列出分类结果以及每个分类中文件的数量。用户可以将报告保存到一个文本文件中。可以使用Python的文件操作来创建并写入报告。 使用Python编写这样一个文件自动分类工具,可以帮助用户快速整理和管理文件,提高工作效率。该工具非常灵活,用户可以根据自己的需求进行规则的设置。同时,Python具有简单易学的语法和丰富的库支持,使得编写这样的工具变得轻松高效。 ### 回答3: Python是一种强大且易于使用的编程语言,可以用于编写各种应用程序和工具。对于文件自动分类工具的编写,Python的文件操作和字符串处理的功能非常适合。 首先,可以使用Python的os模块来遍历指定文件夹中的所有文件。这样可以获取文件夹下的所有文件的路径。 接下来,可以使用Python的shutil模块来创建新的文件夹,并将文件移动到相应的文件夹中。通过判断文件的扩展名,可以将不同类型的文件分类到不同的文件夹中。例如,可以创建一个名为"图片"的文件夹,将扩展名为".jpg"、".png"和".gif"的文件移动到该文件夹中。同样的原理可以应用于其他类型的文件,如文档、音频和视频等。 另外,为了方便用户使用,可以使用Python的argparse模块来接受用户输入的文件夹路径作为参数。这样用户只需在命令行中输入文件夹路径,即可自动将文件分类到相应的文件夹中。同时,可以添加一些错误处理的功能,比如用户输入的文件夹路径不存在或者没有权限访问等。 最后,为了提高用户体验,可以使用Python的tkinter模块或Qt模块等来创建一个用户界面。用户可以通过界面来选择文件夹,并点击一个按钮来开始自动分类的过程。界面还可以显示分类的进度和结果等信息,让用户了解整个过程的运行情况。 综上所述,利用Python编写一个文件自动分类工具是十分可行的。通过利用Python的文件操作、字符串处理和GUI库等功能,可以实现一个简单而实用的工具,提高文件管理的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值