Python的threading模块是一个强大的工具,它提供了高级别的线程编程接口。通过这个模块,Python程序员可以在应用程序中实现多线程并发执行。
线程(Thread)是程序执行流的最小单元,被包涵在进程之中,是进程中的一个实体,是被系统独立调度和分派的基本单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。
当我们用tkinter设计开发桌面程序时,不免需要一个或多个线程执行其他任务,例如:显示实时显示时间日期、动态背景、滚动字幕、插件启动与关闭、后台数据监控等......
在本篇文章结合线程threading与窗口tkinter简单设计一个桌面程序显示滚动字幕和显示时间。
Thread-1 启动
Thread-2 启动
Thread-2 关闭
Thread-1 关闭
"""
桌面程序
"""
# 通配符 "*"
__all__ = ['MyApp', 'ScrollTitle', 'StatusBar']
__all__.extend(['SCROLL_TITLE', 'TITLE_FLAG', 'STATUS_FLAG'])
# 导入内置模块
import tkinter as tk
from threading import Thread, Lock
import time
# 全局变量
SCROLL_TITLE = '' # 滚动标题内容
TITLE_FLAG = True # 滚动标题旗帜
STATUS_FLAG = True # 状态栏旗帜
class MyApp(tk.Tk):
""" 继承tk.Tk, 设计我的桌面程序 """
def __init__(self):
""" 重写父类的构造方法 """
# 调用父类的构造方法
super().__init__()
""" 开始对我的桌面程序功能进行设计 """
self.title('我的桌面程序')
self.geometry('400x300')
self.status = tk.Label(self, relief='groove')
self.status.pack(side='bottom', fill='both')
self.thread_quit = tk.Button(self, text='结束子线程', command=self.quit_thread)
self.thread_quit.pack(expand=True)
global SCROLL_TITLE
SCROLL_TITLE = '欢迎使用我的程序'
self.title_lock = Lock() # 创建互斥锁
# 创建子线程1,执行任务
self.scroll_title = ScrollTitle(self.title, self.title_lock)
self.scroll_title.start() # 启动子线程任务
self.time_lock = Lock() # 创建互斥锁
# 创建子线程2,执行任务
self.status_Bar = StatusBar(self.status, self.time_lock)
self.status_Bar.start() # 启动子线程任务
def quit_thread(self):
""" 结束子线程执行任务 """
global TITLE_FLAG, STATUS_FLAG
# 结束
if TITLE_FLAG:
TITLE_FLAG = False # 结束滚动标题线程运行
STATUS_FLAG = False # 结束状态栏显示时间线程运行
self.thread_quit.configure(text='开启子线程')
else:
TITLE_FLAG = True # 开启滚动标题线程运行
STATUS_FLAG = True # 开启状态栏显示时间线程运行
self.thread_quit.configure(text='开启子线程')
# 创建子线程1,执行任务
self.scroll_title = ScrollTitle(self.title, self.title_lock)
self.scroll_title.start() # 启动子线程任务
# 创建子线程2,执行任务
self.status_Bar = StatusBar(self.status, self.time_lock)
self.status_Bar.start() # 启动子线程任务
class ScrollTitle(Thread):
""" 继承Thread, 设计滚动标题 """
def __init__(self, title, lock, name=None):
""" 重写父类的构造方法 """
# 调用父类的构造方法
super().__init__()
""" 开始对滚动标题进行设计 """
self.scroll_title = title # 标题对象
self.lock = lock # 互斥锁对象
if name: self.name = name # 子线程名字
def run(self):
""" 重写父类的run方法 """
print(self.name, '启动')
# 执行任务
while True:
self.lock.acquire() # 上锁
# 修改数据
for i in range(len(SCROLL_TITLE)):
self.scroll_title(f'{SCROLL_TITLE[i::]}{" "*3}{SCROLL_TITLE[:i:]}')
time.sleep(1)
# 退出条件
if not TITLE_FLAG:
self.lock.release() # 解锁
print(self.name, '关闭')
return
self.lock.release() # 解锁
class StatusBar(Thread):
""" 继承Thread, 设计状态栏显示时间 """
def __init__(self, status, lock, name=None):
""" 重写父类的构造方法 """
# 调用父类的构造方法
super().__init__()
""" 开始对状态栏显示时间进行设计 """
self.status = status # 状态栏对象
self.lock = lock # 互斥锁对象
if name: self.name = name # 子线程名字
def run(self):
""" 重写父类的run方法 """
print(self.name, '启动')
# 执行任务
while True:
if not STATUS_FLAG: break # 退出条件
self.lock.acquire() # 上锁
# 状态栏显示时间
self.status.config(text=f'{time.strftime("%c")}')
self.lock.release() # 解锁
print(self.name, '关闭')
# 代码测试
if __name__ == '__main__':
ui = MyApp() # 实例化桌面程序
ui.mainloop() # 循环窗口运行
else:
print(f'导入【{__name__}】')
作者:周华
创作日期:2024/1/17