python 练习实现倒计时60读秒【第二版】

查看 102|回复 9
作者:bx_liu   
*******************************************第二版相关说明*********************************************************************************************************
1、添加配置前台修改功能;
2、运行程序后,保留第一版双击倒计时弹窗任何一处开始倒计时,倒计时界面可以用鼠标拖动功能,
3、添加F11键开始倒计时,F12键暂停倒计时,再按F12键继续倒计时(此处有待完善重复后有跳秒情况);
4、添加倒计时时间选项10秒、20秒、60秒快捷设置,选后,双击鼠标开始倒计时;(还有点小问题)
第二版代码如下:
[Python] 纯文本查看 复制代码import time
import tkinter as tk
import configparser
from tkinter import Menu
import pygame  # 导入 pygame 库用于播放声音
from tkinter import simpledialog, Toplevel, Button  # 用于弹出输入对话框、新增 Toplevel 和 Button 用于创建自定义窗口和按钮
# 检查配置文件是否存在,不存在则创建默认配置文件
config = configparser.ConfigParser()
try:
    config.read('config.ini')
except FileNotFoundError:
    config['Settings'] = {
       'seconds': '60',
        'font_size': '60',
        'window_width': '200',
        'window_height': '100',
        'countdown_alert_seconds': '5',
        'window_transparency': '0.7'
    }
    with open('config.ini', 'w', encoding='utf-8') as configfile:
        config.write(configfile)
# 获取配置信息
seconds = int(config.get('Settings', 'seconds'))
font_size = int(config.get('Settings', 'font_size'))
window_width = int(config.get('Settings', 'window_width'))
window_height = int(config.get('Settings', 'window_height'))
countdown_alert_seconds = int(config.get('Settings', 'countdown_alert_seconds'))
window_transparency = float(config.get('Settings', 'window_transparency'))
screen_width = tk.Tk().winfo_screenwidth()
screen_height = tk.Tk().winfo_screenheight()
# 创建主窗口实例
root = tk.Tk()
# 全局定义输入框组件
seconds_entry = None
font_size_entry = None
window_width_entry = None
window_height_entry = None
countdown_alert_seconds_entry = None
window_transparency_entry = None
# 定义保存配置函数
def save_config():
    global seconds, font_size, window_width, window_height, countdown_alert_seconds, window_transparency
    new_seconds = seconds_entry.get()
    if new_seconds:
        seconds = int(new_seconds)
        config.set('Settings', 'seconds', new_seconds)
    new_font_size = font_size_entry.get()
    if new_font_size:
        font_size = int(new_font_size)
        config.set('Settings', 'font_size', new_font_size)
    new_window_width = window_width_entry.get()
    if new_window_width:
        window_width = int(new_window_width)
        config.set('Settings', 'window_width', new_window_width)
    new_window_height = window_height_entry.get()
    if new_window_height:
        window_height = int(new_window_height)
        config.set('Settings', 'window_height', new_window_height)
    new_countdown_alert_seconds = countdown_alert_seconds_entry.get()
    if new_countdown_alert_seconds:
        countdown_alert_seconds = int(new_countdown_alert_seconds)
        config.set('Settings', 'countdown_alert_seconds', new_countdown_alert_seconds)
    new_window_transparency = window_transparency_entry.get()
    if new_window_transparency:
        window_transparency = float(new_window_transparency)
        config.set('Settings', 'window_transparency', new_window_transparency)
    with open('config.ini', 'w', encoding='utf-8') as configfile:
        config.write(configfile)
    config_window.destroy()  # 保存后关闭修改配置窗口
def countdown(x_position, y_position):
    root.overrideredirect(True)  # 去除窗口边框
    root.attributes('-alpha', window_transparency)  # 根据配置文件设置 window_transparency
    # 精准计算窗口中心位置坐标,添加边界判断
    x = (screen_width - window_width) // 2
    y = max(0, (screen_height - window_height) // 2)  # 确保 y 坐标不小于 0,防止窗口超出屏幕上方
    root.geometry(f"{window_width}x{window_height}+{x}+{y}")
    label = tk.Label(root, image=None, text=seconds, font=("Arial", font_size), fg="white", bg="black")
    label.pack(fill=tk.BOTH, expand=True)
    # 记录鼠标按下时相对于窗口的坐标
    x_offset = None
    y_offset = None
    def start_move(event):
        nonlocal x_offset, y_offset
        x_offset = event.x
        y_offset = event.y
    def on_move(event):
        nonlocal x_offset, y_offset
        if x_offset is not None and y_offset is not None:
            x = root.winfo_x() + (event.x - x_offset)
            y = root.winfo_y() + (event.y - y_offset)
            root.geometry(f"+{x}+{y}")
    root.bind("[B]", start_move)
    root.bind("[B]", on_move)
    # 定义倒计时启动标志和暂停标志
    countdown_started = False
    paused = False
    remaining_time = seconds  # 存储剩余时间
    def update_countdown():
        nonlocal remaining_time, countdown_started, paused
        if not paused and countdown_started:
            if remaining_time > 0:
                label.config(text=str(remaining_time))
                root.update()
                if remaining_time ", lambda event: start_countdown())
    root.bind("", lambda event: start_countdown())
    root.bind("", lambda event: reset_countdown())
    root.bind("", lambda event: pause_countdown())
    # 创建右键菜单
    popup_menu = Menu(root, tearoff=0)
    # 添加倒计时时间配置选项
    time_menu = Menu(popup_menu, tearoff=0)
    time_menu.add_command(label="10 秒", command=lambda: set_countdown_time(10))
    time_menu.add_command(label="20 秒", command=lambda: set_countdown_time(20))
    time_menu.add_command(label="60 秒", command=lambda: set_countdown_time(60))
    popup_menu.add_cascade(label="倒计时时间", menu=time_menu)
    popup_menu.add_command(label="修改配置文件", command=modify_config)
    popup_menu.add_command(label="退出程序", command=root.quit)
    root.bind("[B]", lambda event: popup_menu.post(event.x_root, event.y_root))
    root.mainloop()
def modify_config():
    global config_window, seconds_entry, font_size_entry, window_width_entry, window_height_entry, countdown_alert_seconds_entry, window_transparency_entry
    config_window = Toplevel(root)  # 创建新的顶层窗口作为修改配置窗口
    config_window.title("修改配置")
    # 倒计时秒数输入框
    seconds_label = tk.Label(config_window, text="倒计时秒数:")
    seconds_label.pack()
    seconds_entry = tk.Entry(config_window)
    seconds_entry.insert(0, str(seconds))
    seconds_entry.pack()
    # 字体大小输入框
    font_size_label = tk.Label(config_window, text="字体大小:")
    font_size_label.pack()
    font_size_entry = tk.Entry(config_window)
    font_size_entry.insert(0, str(font_size))
    font_size_entry.pack()
    # 窗口宽度输入框
    window_width_label = tk.Label(config_window, text="窗口宽度:")
    window_width_label.pack()
    window_width_entry = tk.Entry(config_window)
    window_width_entry.insert(0, str(window_width))
    window_width_entry.pack()
    # 窗口高度输入框
    window_height_label = tk.Label(config_window, text="窗口高度:")
    window_height_label.pack()
    window_height_entry = tk.Entry(config_window)
    window_height_entry.insert(0, str(window_height))
    window_height_entry.pack()
    # 剩余秒提示输入框
    countdown_alert_seconds_label = tk.Label(config_window, text="剩余秒提示:")
    countdown_alert_seconds_label.pack()
    countdown_alert_seconds_entry = tk.Entry(config_window)
    countdown_alert_seconds_entry.insert(0, str(countdown_alert_seconds))
    countdown_alert_seconds_entry.pack()
    # 窗口透明度输入框
    window_transparency_label = tk.Label(config_window, text="window_transparency:")
    window_transparency_label.pack()
    window_transparency_entry = tk.Entry(config_window)
    window_transparency_entry.insert(0, str(window_transparency))
    window_transparency_entry.pack()
    # 保存按钮
    save_button = Button(config_window, text="保存", command=save_config)
    save_button.pack()
# 示例用法:窗口位于屏幕中心(可按需调整坐标)
countdown((screen_width - window_width) // 2, (screen_height - window_height) // 2)
*******************************************以下是第一版信息*******************************************************************************************************今天闲暇练习一下python实现倒计时读秒,大家一起来学习下!提示:【运行后,双击倒计时弹窗任何一处开始倒计时,倒计时界面可以用鼠标拖动哦!】
[Python] 纯文本查看 复制代码import time
import tkinter as tk
import configparser
from tkinter import Menu
import pygame  # 导入 pygame 库用于播放声音
# 检查配置文件是否存在,不存在则创建默认配置文件
config = configparser.ConfigParser()
try:
    config.read('config.ini')
except FileNotFoundError:
    config['Settings'] = {
        'seconds': '60',
        'font_size': '60',
        'window_width': '300',
        'window_height': '200',
        'countdown_alert_seconds': '5',
        'window_transparency': '0.7'
    }
    with open('config.ini', 'w') as configfile:
        config.write(configfile)
# 获取配置信息
seconds = int(config.get('Settings', 'seconds'))
font_size = int(config.get('Settings', 'font_size'))
window_width = int(config.get('Settings', 'window_width'))
window_height = int(config.get('Settings', 'window_height'))
countdown_alert_seconds = int(config.get('Settings', 'countdown_alert_seconds'))
window_transparency = float(config.get('Settings', 'window_transparency'))
screen_width = tk.Tk().winfo_screenwidth()
screen_height = tk.Tk().winfo_screenheight()
# 定义倒计时函数
def countdown(x_position, y_position):
    root = tk.Tk()
    root.overrideredirect(True)  # 去除窗口边框
    root.attributes('-alpha', window_transparency)  # 根据配置文件设置窗口透明度
    root.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}")
    label = tk.Label(root, text=seconds, font=("Arial", font_size), fg="white", bg="black")
    label.pack(fill=tk.BOTH, expand=True)
    # 记录鼠标按下时相对于窗口的坐标
    x_offset = None
    y_offset = None
    def start_move(event):
        nonlocal x_offset, y_offset
        x_offset = event.x
        y_offset = event.y
    def on_move(event):
        nonlocal x_offset, y_offset
        if x_offset is not None and y_offset is not None:
            x = root.winfo_x() + (event.x - x_offset)
            y = root.winfo_y() + (event.y - y_offset)
            root.geometry(f"+{x}+{y}")
    root.bind("[B]", start_move)
    root.bind("[B]", on_move)
    # 定义倒计时启动标志
    countdown_started = False
    def start_countdown(event):
        nonlocal countdown_started
        if not countdown_started:
            for remaining in range(seconds, 0, -1):
                label.config(text=str(remaining))
                root.update()
                time.sleep(1)
                if remaining == countdown_alert_seconds:  # 根据配置文件判断倒计时提醒时间
                    pygame.mixer.init()  # 初始化 pygame 音频模块
                    pygame.mixer.music.load('tick.wav')  # 加载声音文件
                    pygame.mixer.music.play(-1)  # 循环播放声音
                    time.sleep(countdown_alert_seconds)  # 持续播放对应时长
                    pygame.mixer.music.stop()  # 停止播放声音
            label.config(text="时间到")  # 显示时间到
            root.destroy()
            countdown_started = True
    # 绑定快捷键和双击鼠标事件来启动倒计时
    root.bind("", start_countdown)
    root.bind("", start_countdown)
    # 创建右键菜单
    popup_menu = Menu(root, tearoff=0)
    popup_menu.add_command(label="修改配置文件", command=modify_config)
    popup_menu.add_command(label="退出程序", command=root.quit)
    root.bind("[B]", lambda event: popup_menu.post(event.x_root, event.y_root))
    root.mainloop()
def modify_config():
    # 这里可以添加打开配置文件进行修改的具体逻辑,例如使用系统默认文本编辑器打开
    print("打开配置文件进行修改")
# 示例用法:窗口位于屏幕中心(可按需调整坐标)
countdown((screen_width - window_width) // 2, (screen_width - 200) // 2)
配置文件config.ini ,有可能没有权限读写,建立不了config.ini文件,可以手动建立一下,内容如下:
[Settings]
seconds = 60
font_size = 120
window_width = 450
window_height = 300
countdown_alert_seconds = 5
window_transparency = 0.5

倒计时, 窗口

kenxy   

运行出现
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "D:\python_projects\daojishi\daojishi.py", line 24, in
    seconds = int(config.get('Settings', 'seconds'))
  File "D:\Python38\lib\configparser.py", line 781, in get
    d = self._unify_values(section, vars)
  File "D:\Python38\lib\configparser.py", line 1149, in _unify_values
    raise NoSectionError(section) from None
configparser.NoSectionError: No section: 'Settings'
bx_liu
OP
  


kenxy 发表于 2025-1-9 13:50
运行出现
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html

自己创建一个config.ini配置文件:
[Settings]
seconds = 60
font_size = 120
window_width = 450
window_height = 300
countdown_alert_seconds = 5
window_transparency = 0.5
xiaonai   

还能这么写,学到了
bx_liu
OP
  


xiaonai 发表于 2025-1-9 13:26
还能这么写,学到了

哈哈,一起学习
kenxy   

win10,python3.8 不会倒计时
lion25   

还能这么写,学到了
bx_liu
OP
  


kenxy 发表于 2025-1-9 13:53
win10,python3.8 不会倒计时

我的环境是3.10
bx_liu
OP
  


kenxy 发表于 2025-1-9 13:53
win10,python3.8 不会倒计时

要是能看到那个默认的60  双击鼠标开始倒计时,我忘写了,不好意思
liurong3390   

谢谢分享
您需要登录后才可以回帖 登录 | 立即注册

返回顶部